From cc1c7731da98d4b477db29a147569b1aa1afa871 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 27 Jul 2015 09:35:52 -0600 Subject: [PATCH] Sporadic scheduler: Fix budget computations when replenishment intervals are nested --- include/nuttx/sched.h | 2 +- sched/sched/sched_sporadic.c | 36 ++++++++++++++++-------------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 91ec0da0be..0d79941369 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -253,6 +253,7 @@ struct replenishment_s { FAR struct tcb_s *tcb; /* The parent TCB structure */ struct wdog_s timer; /* Timer dedicated to this interval */ + uint32_t budget; /* Current budget time */ bool active; /* True: replenishment instance is busy */ }; @@ -271,7 +272,6 @@ struct sporadic_s uint8_t nrepls; /* Number of active replenishments */ uint32_t repl_period; /* Sporadic replenishment period */ uint32_t budget; /* Sporadic execution budget period */ - uint32_t current; /* Unrealized, current budget time */ uint32_t pending; /* Unrealized, pending execution budget */ #ifdef CONFIG_SCHED_TICKLESS diff --git a/sched/sched/sched_sporadic.c b/sched/sched/sched_sporadic.c index bbe61d0abb..87ae7b6b99 100644 --- a/sched/sched/sched_sporadic.c +++ b/sched/sched/sched_sporadic.c @@ -119,8 +119,8 @@ static int sporadic_budget_start(FAR struct tcb_s *tcb, /* Start the next replenishment interval */ - tcb->timeslice = budget; - sporadic->current = budget; + tcb->timeslice = budget; + repl->budget = budget; #ifdef CONFIG_SCHED_TICKLESS /* Save the time that the replenishment interval started */ @@ -334,15 +334,14 @@ static int sporadic_interval_start(FAR struct replenishment_s *repl) /* Enter the low-priority phase of the replenishment cycle */ tcb->timeslice = 0; - sporadic->current = 0; /* Calculate the remainder of the replenishment interval. This is * permitted to be zero, in which case we just restart the budget * interval without lowering the priority. */ - DEBUGASSERT(sporadic->repl_period >= sporadic->budget); - remainder = sporadic->repl_period - sporadic->budget; + DEBUGASSERT(sporadic->repl_period >= repl->budget); + remainder = sporadic->repl_period - repl->budget; if (remainder == 0) { return sporadic_budget_next(repl); @@ -408,9 +407,9 @@ static void sporadic_budget_expire(int argc, wdparm_t arg1, ...) { DEBUGASSERT(repl->active && sporadic->nrepls > 0); - tcb->timeslice = -1; - sporadic->current = 0; - repl->active = false; + tcb->timeslice = -1; + repl->budget = 0; + repl->active = false; sporadic->nrepls--; return; } @@ -422,8 +421,8 @@ static void sporadic_budget_expire(int argc, wdparm_t arg1, ...) * not execute. */ - DEBUGASSERT(sporadic->current >= tcb->timeslice); - pending = sporadic->pending + sporadic->current - tcb->timeslice; + DEBUGASSERT(repl->budget >= tcb->timeslice); + pending = sporadic->pending + repl->budget - tcb->timeslice; if (pending > sporadic->budget) { /* Limit to the full budget. This can happen if we are falling @@ -436,7 +435,9 @@ static void sporadic_budget_expire(int argc, wdparm_t arg1, ...) sporadic->pending = pending; - /* Drop the priority of the thread and start the timer for the rest of the interval */ + /* Drop the priority of the thread and start the timer for the rest of + * the interval. + */ DEBUGVERIFY(sporadic_interval_start(repl)); } @@ -756,7 +757,6 @@ int sched_sporadic_reset(FAR struct tcb_s *tcb) sporadic->nrepls = 0; sporadic->repl_period = 0; sporadic->budget = 0; - sporadic->current = 0; sporadic->pending = 0; return OK; } @@ -814,7 +814,7 @@ int sched_sporadic_resume(FAR struct tcb_s *tcb) * not want to start a new timer in these cases. */ - if (tcb->timeslice > 0 && tcb->timeslice < sporadic->current) + if (tcb->timeslice > 0 && tcb->timeslice < sporadic->budget) { /* Allocate a new replenishment timer. This will limit us to * to maximum number of replenishments (max_repl). @@ -902,7 +902,7 @@ int sched_sporadic_suspend(FAR struct tcb_s *tcb, * not want to start a new timer in these cases. */ - if (tcb->timeslice > 0 && tcb->timeslice < sporadic->current) + if (tcb->timeslice > 0 && tcb->timeslice < sporadic->budget) { /* Get the difference in time between the time that the scheduler just * ran and time time that the thread was spuspended. This difference, @@ -1024,7 +1024,6 @@ uint32_t sched_sporadic_process(FAR struct tcb_s *tcb, uint32_t ticks, sporadic_timer_cancel(tcb); tcb->timeslice = -1; - sporadic->current = 0; return 0; } @@ -1042,7 +1041,6 @@ uint32_t sched_sporadic_process(FAR struct tcb_s *tcb, uint32_t ticks, if (noswitches) { tcb->timeslice = 1; - sporadic->current = 0; return 1; } @@ -1053,8 +1051,7 @@ uint32_t sched_sporadic_process(FAR struct tcb_s *tcb, uint32_t ticks, if (sporadic->budget >= sporadic->repl_period) { - tcb->timeslice = sporadic->budget; - sporadic->current = sporadic->budget; + tcb->timeslice = sporadic->budget; return sporadic->budget; } @@ -1110,8 +1107,7 @@ void sched_sporadic_lowpriority(FAR struct tcb_s *tcb) * redundant). */ - tcb->timeslice = 0; - sporadic->current = 0; + tcb->timeslice = 0; /* Allocate a new replenishment timer. There should be no timers * active at this phase since they were stopped in sched_sporadic_process().