From f1f5e7dafd5380ea284c3f4257702d33cdc1d711 Mon Sep 17 00:00:00 2001 From: yushuailong Date: Fri, 31 Jul 2026 11:32:57 +0800 Subject: [PATCH] sched/sched: Fix uninitialized sporadic params returned by nxsched_get_param() When querying the calling task itself (pid == 0 or the caller's own pid), nxsched_get_param() only filled in sched_priority and never touched the SCHED_SPORADIC related members (sched_ss_low_priority, sched_ss_max_repl, sched_ss_repl_period and sched_ss_init_budget). With CONFIG_SCHED_SPORADIC enabled, the caller received uninitialized stack garbage in these fields, and a task running under the sporadic policy could not retrieve its own sporadic parameters. Fix this by factoring the sporadic parameter fill-in into a common helper nxsched_get_sporadic_param() shared by both the self-query and the lookup paths, so both paths now return identical information. The self-query path keeps its original fast-path behavior: no TCB lookup and a lock-free read of sched_priority. Only the read of the sporadic state is wrapped in a critical section, because tcb->sporadic may be freed concurrently, e.g. by sched_setscheduler() from another CPU switching the task away from SCHED_SPORADIC. Signed-off-by: yushuailong --- sched/sched/sched_getparam.c | 85 ++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 27 deletions(-) diff --git a/sched/sched/sched_getparam.c b/sched/sched/sched_getparam.c index 7232134e2cb..b1a83bc537b 100644 --- a/sched/sched/sched_getparam.c +++ b/sched/sched/sched_getparam.c @@ -36,6 +36,51 @@ #include "clock/clock.h" #include "sched/sched.h" +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxsched_get_sporadic_param + * + * Description: + * Fill in the SCHED_SPORADIC related members of param from the TCB. + * Must be called within a critical section since the sporadic scheduler + * state may be modified concurrently. + * + ****************************************************************************/ + +#ifdef CONFIG_SCHED_SPORADIC +static void nxsched_get_sporadic_param(FAR struct tcb_s *tcb, + FAR struct sched_param *param) +{ + if ((tcb->flags & TCB_FLAG_POLICY_MASK) == TCB_FLAG_SCHED_SPORADIC) + { + FAR struct sporadic_s *sporadic = tcb->sporadic; + DEBUGASSERT(sporadic != NULL); + + /* Return parameters associated with SCHED_SPORADIC */ + + param->sched_ss_low_priority = (int)sporadic->low_priority; + param->sched_ss_max_repl = (int)sporadic->max_repl; + + clock_ticks2time(¶m->sched_ss_repl_period, + sporadic->repl_period); + clock_ticks2time(¶m->sched_ss_init_budget, + sporadic->budget); + } + else + { + param->sched_ss_low_priority = 0; + param->sched_ss_max_repl = 0; + param->sched_ss_repl_period.tv_sec = 0; + param->sched_ss_repl_period.tv_nsec = 0; + param->sched_ss_init_budget.tv_sec = 0; + param->sched_ss_init_budget.tv_nsec = 0; + } +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -81,14 +126,24 @@ int nxsched_get_param(pid_t pid, FAR struct sched_param *param) } else { - /* Check if the task to restart is the calling task */ + /* Check if the PID is that of the calling task */ rtcb = this_task(); if (pid == 0 || pid == rtcb->pid) { - /* Return the priority if the calling task. */ + /* Return the priority of the calling task. */ param->sched_priority = (int)rtcb->sched_priority; + +#ifdef CONFIG_SCHED_SPORADIC + /* The sporadic state may be modified concurrently, e.g. by + * sched_setparam() from another CPU, so it must be protected. + */ + + flags = enter_critical_section(); + nxsched_get_sporadic_param(rtcb, param); + leave_critical_section(flags); +#endif } /* This PID is not for the calling task, we will have to look it up */ @@ -112,31 +167,7 @@ int nxsched_get_param(pid_t pid, FAR struct sched_param *param) param->sched_priority = (int)tcb->sched_priority; #ifdef CONFIG_SCHED_SPORADIC - if ((tcb->flags & TCB_FLAG_POLICY_MASK) == - TCB_FLAG_SCHED_SPORADIC) - { - FAR struct sporadic_s *sporadic = tcb->sporadic; - DEBUGASSERT(sporadic != NULL); - - /* Return parameters associated with SCHED_SPORADIC */ - - param->sched_ss_low_priority = (int)sporadic->low_priority; - param->sched_ss_max_repl = (int)sporadic->max_repl; - - clock_ticks2time(¶m->sched_ss_repl_period, - sporadic->repl_period); - clock_ticks2time(¶m->sched_ss_init_budget, - sporadic->budget); - } - else - { - param->sched_ss_low_priority = 0; - param->sched_ss_max_repl = 0; - param->sched_ss_repl_period.tv_sec = 0; - param->sched_ss_repl_period.tv_nsec = 0; - param->sched_ss_init_budget.tv_sec = 0; - param->sched_ss_init_budget.tv_nsec = 0; - } + nxsched_get_sporadic_param(tcb, param); #endif }