sched/timedwait: Ensure critical section for nxsig_timeout

nxsig_timeout calls nxsched_add_readytorun and up_switch_context, so
must be in critical section.
nxsig_timeout is used as wdentry in nxsig_clockwait

See wd_expiration CALL_FUNC is not in critical section.

Signed-off-by: Serg Podtynnyi <serg@podtynnyi.com>
This commit is contained in:
Serg Podtynnyi
2025-05-14 22:52:10 +07:00
committed by Xiang Xiao
parent 57a7cb503a
commit c5757ed71f
+7 -13
View File
@@ -78,20 +78,14 @@
static void nxsig_timeout(wdparm_t arg) static void nxsig_timeout(wdparm_t arg)
{ {
FAR struct tcb_s *wtcb = (FAR struct tcb_s *)(uintptr_t)arg; FAR struct tcb_s *wtcb = (FAR struct tcb_s *)(uintptr_t)arg;
#ifdef CONFIG_SMP
irqstate_t flags; irqstate_t flags;
/* We must be in a critical section in order to call up_switch_context() /* We must be in a critical section in order to call up_switch_context()
* below. If we are running on a single CPU architecture, then we know * below.
* interrupts a disabled an there is no need to explicitly call
* enter_critical_section(). However, in the SMP case,
* enter_critical_section() does much more than just disable interrupts on
* the local CPU; it also manages spinlocks to assure the stability of the
* TCB that we are manipulating.
*/ */
flags = enter_critical_section(); flags = enter_critical_section();
#endif
/* There may be a race condition -- make sure the task is /* There may be a race condition -- make sure the task is
* still waiting for a signal * still waiting for a signal
@@ -127,9 +121,7 @@ static void nxsig_timeout(wdparm_t arg)
} }
} }
#ifdef CONFIG_SMP
leave_critical_section(flags); leave_critical_section(flags);
#endif
} }
/**************************************************************************** /****************************************************************************
@@ -252,8 +244,8 @@ int nxsig_clockwait(int clockid, int flags,
FAR const struct timespec *rqtp, FAR const struct timespec *rqtp,
FAR struct timespec *rmtp) FAR struct timespec *rmtp)
{ {
FAR struct tcb_s *rtcb = this_task(); FAR struct tcb_s *rtcb;
irqstate_t iflags; irqstate_t iflags;
clock_t expect = 0; clock_t expect = 0;
clock_t stop; clock_t stop;
@@ -297,6 +289,7 @@ int nxsig_clockwait(int clockid, int flags,
#endif #endif
iflags = enter_critical_section(); iflags = enter_critical_section();
rtcb = this_task();
if (rqtp) if (rqtp)
{ {
@@ -394,7 +387,7 @@ int nxsig_clockwait(int clockid, int flags,
int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info,
FAR const struct timespec *timeout) FAR const struct timespec *timeout)
{ {
FAR struct tcb_s *rtcb = this_task(); FAR struct tcb_s *rtcb;
sigset_t intersection; sigset_t intersection;
FAR sigpendq_t *sigpend; FAR sigpendq_t *sigpend;
irqstate_t flags; irqstate_t flags;
@@ -410,6 +403,7 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info,
*/ */
flags = enter_critical_section(); flags = enter_critical_section();
rtcb = this_task();
/* Check if there is a pending signal corresponding to one of the /* Check if there is a pending signal corresponding to one of the
* signals in the pending signal set argument. * signals in the pending signal set argument.