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 <yyyusl@qq.com>
This commit is contained in:
yushuailong 2026-07-31 11:32:57 +08:00
parent f0c94bb64a
commit f1f5e7dafd

View file

@ -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(&param->sched_ss_repl_period,
sporadic->repl_period);
clock_ticks2time(&param->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(&param->sched_ss_repl_period,
sporadic->repl_period);
clock_ticks2time(&param->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
}