This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 4a34293263527b60a0ec112c6ad6bdfd5f7ff43a Author: yushuailong <[email protected]> AuthorDate: Mon Sep 7 21:13:10 2026 +0800 sched: Centralize sporadic parameter validation Sporadic scheduling parameters are processed independently by sched_setparam(), sched_setscheduler(), and pthread_create(). The three paths currently validate different subsets of the parameters. In particular, pthread_create() does not validate sched_ss_max_repl and only requires the replenishment period to be greater than the budget, while the scheduler interfaces enforce the implementation's 50 percent duty-cycle limit. Add nxsched_validate_sporadic() to validate the common parameters and convert the replenishment period and budget to ticks. Use it from all paths that directly initialize or update sporadic scheduler state. Express the duty-cycle check using division to avoid overflow when doubling a clock_t value. Assisted-by: OpenAI Codex Signed-off-by: yushuailong <[email protected]> --- sched/pthread/pthread_create.c | 43 +++++++++--------- sched/sched/sched.h | 3 ++ sched/sched/sched_setparam.c | 94 ++++++++++++---------------------------- sched/sched/sched_setscheduler.c | 90 +++++++++++++------------------------- sched/sched/sched_sporadic.c | 65 +++++++++++++++++++++++++++ 5 files changed, 145 insertions(+), 150 deletions(-) diff --git a/sched/pthread/pthread_create.c b/sched/pthread/pthread_create.c index 19b43f85895..684495b101c 100644 --- a/sched/pthread/pthread_create.c +++ b/sched/pthread/pthread_create.c @@ -189,7 +189,6 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, struct sched_param param; FAR struct tcb_s *parent; int policy; - int errcode; int ret; DEBUGASSERT(trampoline != NULL); @@ -238,7 +237,6 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, ret = addrenv_join(this_task(), ptcb); if (ret < 0) { - errcode = -ret; goto errout_with_tcb; } #endif @@ -265,7 +263,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, if (ret != OK) { - errcode = ENOMEM; + ret = -ENOMEM; goto errout_with_tcb; } @@ -275,7 +273,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, ret = up_addrenv_kstackalloc(ptcb); if (ret < 0) { - errcode = ENOMEM; + ret = -ENOMEM; goto errout_with_tcb; } #endif @@ -294,7 +292,6 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, ret = nxsched_get_param(0, ¶m); if (ret < 0) { - errcode = -ret; goto errout_with_tcb; } @@ -303,7 +300,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, policy = nxsched_get_scheduler(0); if (policy < 0) { - errcode = -policy; + ret = policy; goto errout_with_tcb; } } @@ -331,24 +328,28 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, clock_t repl_ticks; clock_t budget_ticks; - /* Convert timespec values to system clock ticks */ + /* Validate the priority before initializing sporadic state */ - repl_ticks = clock_time2ticks(¶m.sched_ss_repl_period); - budget_ticks = clock_time2ticks(¶m.sched_ss_init_budget); - - /* The replenishment period must be greater than or equal to the - * budget period. - */ - - if (repl_ticks < budget_ticks) + if (param.sched_priority < SCHED_PRIORITY_MIN || + param.sched_priority > SCHED_PRIORITY_MAX) { - errcode = EINVAL; - goto errout_with_tcb; + ret = -EINVAL; + } + else + { + /* Validate the sporadic parameters */ + + ret = nxsched_validate_sporadic(¶m, &repl_ticks, + &budget_ticks); } /* Initialize the sporadic policy */ - ret = nxsched_initialize_sporadic(ptcb); + if (ret >= 0) + { + ret = nxsched_initialize_sporadic(ptcb); + } + if (ret >= 0) { sporadic = ptcb->sporadic; @@ -371,7 +372,6 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, if (ret < 0) { - errcode = -ret; goto errout_with_tcb; } } @@ -383,7 +383,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, entry); if (ret != OK) { - errcode = EBUSY; + ret = -EBUSY; goto errout_with_tcb; } @@ -392,7 +392,6 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, ret = tls_init_info(ptcb); if (ret != OK) { - errcode = -ret; goto errout_with_tcb; } @@ -465,5 +464,5 @@ errout_with_tcb: ptcb->group = NULL; nxsched_release_tcb(ptcb, TCB_FLAG_TTYPE_PTHREAD); - return errcode; + return -ret; } diff --git a/sched/sched/sched.h b/sched/sched/sched.h index f1a8776fcf1..212f379a71c 100644 --- a/sched/sched/sched.h +++ b/sched/sched/sched.h @@ -367,6 +367,9 @@ void nxsched_resume_roundrobin(FAR struct tcb_s *tcb); #endif #ifdef CONFIG_SCHED_SPORADIC +int nxsched_validate_sporadic(FAR const struct sched_param *param, + FAR clock_t *repl_ticks, + FAR clock_t *budget_ticks); int nxsched_initialize_sporadic(FAR struct tcb_s *tcb); int nxsched_start_sporadic(FAR struct tcb_s *tcb); int nxsched_stop_sporadic(FAR struct tcb_s *tcb); diff --git a/sched/sched/sched_setparam.c b/sched/sched/sched_setparam.c index 61e8c7a1b04..d9f031712ca 100644 --- a/sched/sched/sched_setparam.c +++ b/sched/sched/sched_setparam.c @@ -35,7 +35,6 @@ #include <nuttx/irq.h> #include <nuttx/arch.h> -#include "clock/clock.h" #include "sched/sched.h" /**************************************************************************** @@ -47,6 +46,9 @@ static inline_function int set_sporadic_param(FAR const struct sched_param *param, FAR struct tcb_s *tcb) { + FAR struct sporadic_s *sporadic; + clock_t repl_ticks; + clock_t budget_ticks; irqstate_t flags; int ret = OK; @@ -54,83 +56,41 @@ int set_sporadic_param(FAR const struct sched_param *param, if ((tcb->flags & TCB_FLAG_POLICY_MASK) == TCB_FLAG_SCHED_SPORADIC) { - FAR struct sporadic_s *sporadic; - clock_t repl_ticks; - clock_t budget_ticks; - - if (param->sched_ss_max_repl >= 1 && - param->sched_ss_max_repl <= CONFIG_SCHED_SPORADIC_MAXREPL) + ret = nxsched_validate_sporadic(param, &repl_ticks, &budget_ticks); + if (ret < 0) { - /* Convert timespec values to system clock ticks */ - - repl_ticks = clock_time2ticks(¶m->sched_ss_repl_period); - budget_ticks = clock_time2ticks(¶m->sched_ss_init_budget); - - /* Avoid zero/negative times */ - - if (repl_ticks < 1) - { - repl_ticks = 1; - } - - if (budget_ticks < 1) - { - budget_ticks = 1; - } + return ret; + } - /* The replenishment period must be greater than or equal to the - * budget period. - */ + /* Stop/reset current sporadic scheduling */ -#if 1 - /* REVISIT: In the current implementation, the budget cannot exceed - * half the duty. + flags = enter_critical_section(); + ret = nxsched_reset_sporadic(tcb); + if (ret >= 0) + { + /* Save the sporadic scheduling parameters and reset to the + * beginning to the replenishment interval. */ - if (repl_ticks >= (2 * budget_ticks)) -#else - if (repl_ticks < budget_ticks) -#endif - { - /* Stop/reset current sporadic scheduling */ - - flags = enter_critical_section(); - ret = nxsched_reset_sporadic(tcb); - if (ret >= 0) - { - /* Save the sporadic scheduling parameters and reset to the - * beginning to the replenishment interval. - */ + tcb->timeslice = budget_ticks; - tcb->timeslice = budget_ticks; + sporadic = tcb->sporadic; + DEBUGASSERT(sporadic != NULL); - sporadic = tcb->sporadic; - DEBUGASSERT(sporadic != NULL); + sporadic->hi_priority = param->sched_priority; + sporadic->low_priority = param->sched_ss_low_priority; + sporadic->max_repl = param->sched_ss_max_repl; + sporadic->repl_period = repl_ticks; + sporadic->budget = budget_ticks; - sporadic->hi_priority = param->sched_priority; - sporadic->low_priority = param->sched_ss_low_priority; - sporadic->max_repl = param->sched_ss_max_repl; - sporadic->repl_period = repl_ticks; - sporadic->budget = budget_ticks; + /* And restart at the next replenishment interval */ - /* And restart at the next replenishment interval */ - - ret = nxsched_start_sporadic(tcb); - } + ret = nxsched_start_sporadic(tcb); + } - /* Restore interrupts and handle any pending work */ + /* Restore interrupts and handle any pending work */ - leave_critical_section(flags); - } - else - { - ret = -EINVAL; - } - } - else - { - ret = -EINVAL; - } + leave_critical_section(flags); } return ret; diff --git a/sched/sched/sched_setscheduler.c b/sched/sched/sched_setscheduler.c index c5a7ec74be8..fd6f632657c 100644 --- a/sched/sched/sched_setscheduler.c +++ b/sched/sched/sched_setscheduler.c @@ -37,7 +37,6 @@ #include <nuttx/arch.h> #include "sched/sched.h" -#include "clock/clock.h" /**************************************************************************** * Private Functions @@ -51,76 +50,45 @@ int process_sporadic(FAR struct tcb_s *tcb, FAR struct sporadic_s *sporadic; clock_t repl_ticks; clock_t budget_ticks; - int ret = -EINVAL; + int ret; - if (param->sched_ss_max_repl >= 1 && - param->sched_ss_max_repl <= CONFIG_SCHED_SPORADIC_MAXREPL) + ret = nxsched_validate_sporadic(param, &repl_ticks, &budget_ticks); + if (ret < 0) { - /* Convert timespec values to system clock ticks */ - - repl_ticks = clock_time2ticks(¶m->sched_ss_repl_period); - budget_ticks = clock_time2ticks(¶m->sched_ss_init_budget); - - /* Avoid zero/negative times */ - - if (repl_ticks < 1) - { - repl_ticks = 1; - } - - if (budget_ticks < 1) - { - budget_ticks = 1; - } - - /* The replenishment period must be greater than or equal to the - * budget period. - */ - -#if 1 - /* REVISIT: In the current implementation, the budget cannot - * exceed half the duty. - */ + return ret; + } - if (repl_ticks >= (2 * budget_ticks)) -#else - if (repl_ticks < budget_ticks) -#endif - { - /* Initialize or reset current sporadic scheduling */ + /* Initialize or reset current sporadic scheduling */ - if ((tcb->flags & TCB_FLAG_POLICY_MASK) == - TCB_FLAG_SCHED_SPORADIC) - { - ret = nxsched_reset_sporadic(tcb); - } - else - { - ret = nxsched_initialize_sporadic(tcb); - } + if ((tcb->flags & TCB_FLAG_POLICY_MASK) == TCB_FLAG_SCHED_SPORADIC) + { + ret = nxsched_reset_sporadic(tcb); + } + else + { + ret = nxsched_initialize_sporadic(tcb); + } - /* Save the sporadic scheduling parameters. */ + /* Save the sporadic scheduling parameters. */ - if (ret >= 0) - { - tcb->flags &= ~TCB_FLAG_POLICY_MASK; - tcb->flags |= TCB_FLAG_SCHED_SPORADIC; - tcb->timeslice = budget_ticks; + if (ret >= 0) + { + tcb->flags &= ~TCB_FLAG_POLICY_MASK; + tcb->flags |= TCB_FLAG_SCHED_SPORADIC; + tcb->timeslice = budget_ticks; - sporadic = tcb->sporadic; - DEBUGASSERT(sporadic != NULL); + sporadic = tcb->sporadic; + DEBUGASSERT(sporadic != NULL); - sporadic->hi_priority = param->sched_priority; - sporadic->low_priority = param->sched_ss_low_priority; - sporadic->max_repl = param->sched_ss_max_repl; - sporadic->repl_period = repl_ticks; - sporadic->budget = budget_ticks; + sporadic->hi_priority = param->sched_priority; + sporadic->low_priority = param->sched_ss_low_priority; + sporadic->max_repl = param->sched_ss_max_repl; + sporadic->repl_period = repl_ticks; + sporadic->budget = budget_ticks; - /* And restart at the next replenishment interval */ + /* And restart at the next replenishment interval */ - ret = nxsched_start_sporadic(tcb); - } - } + ret = nxsched_start_sporadic(tcb); } return ret; diff --git a/sched/sched/sched_sporadic.c b/sched/sched/sched_sporadic.c index 9991ae3d398..86b0b139574 100644 --- a/sched/sched/sched_sporadic.c +++ b/sched/sched/sched_sporadic.c @@ -755,6 +755,71 @@ FAR struct replenishment_s * * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: nxsched_validate_sporadic + * + * Description: + * Validate sporadic scheduling parameters and convert the replenishment + * period and initial budget to system clock ticks. + * + * Input Parameters: + * param - Sporadic scheduling parameters to validate. + * repl_ticks - Location to return the replenishment period in ticks. + * budget_ticks - Location to return the initial budget in ticks. + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int nxsched_validate_sporadic(FAR const struct sched_param *param, + FAR clock_t *repl_ticks, + FAR clock_t *budget_ticks) +{ + clock_t repl; + clock_t budget; + + if (param->sched_ss_low_priority < SCHED_PRIORITY_MIN || + param->sched_ss_low_priority > SCHED_PRIORITY_MAX || + param->sched_ss_max_repl < 1 || + param->sched_ss_max_repl > CONFIG_SCHED_SPORADIC_MAXREPL) + { + return -EINVAL; + } + + /* Convert timespec values to system clock ticks */ + + repl = clock_time2ticks(¶m->sched_ss_repl_period); + budget = clock_time2ticks(¶m->sched_ss_init_budget); + + /* Avoid zero/negative times */ + + if (repl < 1) + { + repl = 1; + } + + if (budget < 1) + { + budget = 1; + } + + /* REVISIT: In the current implementation, the budget cannot exceed + * half the replenishment period. Use division instead of doubling the + * budget to avoid signed overflow. + */ + + if (budget > repl / 2) + { + return -EINVAL; + } + + *repl_ticks = repl; + *budget_ticks = budget; + return OK; +} + /**************************************************************************** * Name: nxsched_initialize_sporadic *
