diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 71565990d7a..7e07490e7b4 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -273,10 +273,7 @@ struct sporadic_s uint8_t nrepls; /* Number of active replenishments */ uint32_t repl_period; /* Sporadic replenishment period */ uint32_t budget; /* Sporadic execution budget period */ - -#ifdef CONFIG_SCHED_TICKLESS - struct timespec sched_time; /* Time in ticks last processed */ -#endif + uint32_t eventtime; /* Time thread suspended or [re-]started */ /* This is the last interval timer activated */ diff --git a/sched/sched/sched.h b/sched/sched/sched.h index 59e62716f83..826be4a708e 100644 --- a/sched/sched/sched.h +++ b/sched/sched/sched.h @@ -251,10 +251,7 @@ int sched_sporadic_start(FAR struct tcb_s *tcb); int sched_sporadic_stop(FAR struct tcb_s *tcb); int sched_sporadic_reset(FAR struct tcb_s *tcb); int sched_sporadic_resume(FAR struct tcb_s *tcb); -#if defined(CONFIG_SCHED_TICKLESS) || defined(CONFIG_SPORADIC_INSTRUMENTATION) -int sched_sporadic_suspend(FAR struct tcb_s *tcb, - FAR const struct timespec *suspend_time); -#endif +int sched_sporadic_suspend(FAR struct tcb_s *tcb); uint32_t sched_sporadic_process(FAR struct tcb_s *tcb, uint32_t ticks, bool noswitches); void sched_sporadic_lowpriority(FAR struct tcb_s *tcb); diff --git a/sched/sched/sched_sporadic.c b/sched/sched/sched_sporadic.c index 1b35b94b05e..80908ee3bdb 100755 --- a/sched/sched/sched_sporadic.c +++ b/sched/sched/sched_sporadic.c @@ -198,6 +198,10 @@ static int sporadic_budget_start(FAR struct tcb_s *tcb, DEBUGVERIFY(wd_start(&repl->timer, budget, sporadic_budget_expire, 1, (wdentry_t)repl)); + /* Save the time that the thread was started */ + + sporadic->eventtime = clock_systimer(); + /* Then reprioritize to the higher priority */ return sporadic_set_hipriority(tcb); @@ -655,11 +659,6 @@ int sched_sporadic_start(FAR struct tcb_s *tcb) DEBUGASSERT(tcb && tcb->sporadic); sporadic = tcb->sporadic; - DEBUGASSERT(sporadic->low_priority <= sporadic->hi_priority); - DEBUGASSERT(sporadic->max_repl <= CONFIG_SCHED_SPORADIC_MAXREPL); - DEBUGASSERT(sporadic->budget > 0 && sporadic->budget <= sporadic->repl_period); - DEBUGASSERT(sporadic->nrepls == 0 && sporadic->active == NULL); - /* Allocate the first replenishment timer (should never fail) */ repl = sporadic_alloc_repl(sporadic); @@ -769,6 +768,7 @@ int sched_sporadic_reset(FAR struct tcb_s *tcb) sporadic->nrepls = 0; sporadic->repl_period = 0; sporadic->budget = 0; + sporadic->eventtime = 0; sporadic->active = NULL; return OK; } @@ -803,8 +803,9 @@ int sched_sporadic_resume(FAR struct tcb_s *tcb) { FAR struct sporadic_s *sporadic; FAR struct replenishment_s *repl; - uint32_t budget; + uint32_t unrealized; uint32_t last; + uint32_t now; DEBUGASSERT(tcb && tcb->sporadic); sporadic = tcb->sporadic; @@ -821,80 +822,72 @@ int sched_sporadic_resume(FAR struct tcb_s *tcb) if (tcb->timeslice > 0) { - /* Get the last budgeted time */ + /* Save the time that the thread was [re-]started */ - DEBUGASSERT(sporadic->active); - last = sporadic->active->budget; + now = clock_systimer(); -#ifdef CONFIG_SCHED_TICKLESS - /* Get the difference in time between the time that the scheduler just - * ran and time time that the thread was suspended. This difference, - * then, is the unaccounted for time between the time that the timer - * was started and when the thread was suspended. - */ + /* Unrealized budget time while the thread was suspended */ - clock_timespec_subtract(suspend_time, &sporadic->sched_time, - &elapsed_time); + unrealized = sporadic->eventtime - now; + sporadic->eventtime = now; - /* Convert to ticks */ + /* Ignore very short pre-emptions that are below our timing resolution. */ - elapsed_ticks = SEC2TICK(elapsed_time.tv_sec); - elapsed_ticks += NSEC2TICK(elapsed_time.tv_nsec); - - /* One possibility is that the the elapsed time is greater than the - * time remaining in the time slice. This is a a race condition. It - * means that the timer has just expired. the interrupt will occu - * soon. - */ - - if (elapsed_ticks >= tcb->timeslice) + if (unrealized > 0) { - return; - } - - /* Otherwise, the unrealized time in this budget is the sum time slice - * value minus, the time from the unexpired timer. - */ - - tcb->timeslice -= (int32_t)elapsed_ticks; -#endif - /* This function could also be called before the budget period has had - * a chance to run, i.e., when the value of timeslice has not been - * decremented and is still equal to the initial value. - * - * This latter case could occur if the thread has never had a chance - * to run and is also very likely when the thread is just restarted - * after raising its priority at the beginning of the budget period. - * We would not want to start a new timer in these cases. - */ - - if (tcb->timeslice < last) - { - /* Allocate a new replenishment timer. This will limit us to - * to maximum number of replenishments (max_repl). + /* Handle any part of the budget that was not utilized. + * + * current = The initial budget at the beginning of the + * interval. + * urealized = The unused part of that budget when the + * thread did not execute. */ - repl = sporadic_alloc_repl(sporadic); - if (repl != NULL) + if (unrealized >= tcb->timeslice) { - return sporadic_budget_start(tcb, repl, tcb->timeslice); + /* We lost the remainder of the timeslice, (and then some). + * No point in starting more timers. + */ + + return OK; } - /* We need to return success even on a failure to allocate. Doing - * nothing is our fall-back behavior and that is not a failure from - * the standpoint of higher level logic. + DEBUGASSERT(sporadic->active); + tcb->timeslice -= unrealized; + sporadic->active->unrealized = unrealized; + + /* Get the last budgeted time */ + + last = sporadic->active->budget; + + /* This function could also be called before the budget period + * has had a chance to run, i.e., when the value of timeslice + * has not been decremented and is still equal to the initial + * value. */ - slldbg("Failed to allocate timer, nrepls=%d\n", sporadic->nrepls); + if (tcb->timeslice < last) + { + /* Allocate a new replenishment timer. This will limit us to + * to maximum number of replenishments (max_repl). + */ + + repl = sporadic_alloc_repl(sporadic); + if (repl != NULL) + { + return sporadic_budget_start(tcb, repl, tcb->timeslice); + } + + /* We need to return success even on a failure to allocate. + * Doing nothing is our fall-back behavior and that is not a + * failure from the standpoint of higher level logic. + */ + + slldbg("Failed to allocate timer, nrepls=%d\n", sporadic->nrepls); + } } } -#ifdef CONFIG_SCHED_TICKLESS - /* Reset to the resume time */ - - (void)up_timer_gettime(&sporadic->sched_time); -#endif - return OK; } @@ -923,14 +916,9 @@ int sched_sporadic_resume(FAR struct tcb_s *tcb) * ****************************************************************************/ -int sched_sporadic_suspend(FAR struct tcb_s *tcb, - FAR const struct timespec *suspend_time) +int sched_sporadic_suspend(FAR struct tcb_s *tcb) { FAR struct sporadic_s *sporadic; -#ifdef CONFIG_SCHED_TICKLESS - struct timespec elapsed_time; - uint32_t elapsed_ticks; -#endif DEBUGASSERT(tcb && tcb->sporadic); sporadic = tcb->sporadic; @@ -941,65 +929,9 @@ int sched_sporadic_suspend(FAR struct tcb_s *tcb, arch_sporadic_suspend(tcb); #endif - /* Check if are in the budget portion of the replenishment interval. We - * know this is the case if the current timeslice is non-zero. - * - * This function could also be called before the budget period has had a - * chance to run, i.e., when the value of timeslice has not been decremented - * and is still equal to the initial value. - * - * This latter case could occur if the thread has never had a chance to - * run and is also very likely when the thread is just restarted after - * raising its priority at the beginning of the budget period. We would - * not want to start a new timer in these cases. - */ - - if (tcb->timeslice > 0) - { -#ifdef CONFIG_SCHED_TICKLESS - /* Get the difference in time between the time that the scheduler just - * ran and time time that the thread was suspended. This difference, - * then, is the unaccounted for time between the time that the timer - * was started and when the thread was suspended. - */ - - clock_timespec_subtract(suspend_time, &sporadic->sched_time, - &elapsed_time); - - /* Convert to ticks */ - - elapsed_ticks = SEC2TICK(elapsed_time.tv_sec); - elapsed_ticks += NSEC2TICK(elapsed_time.tv_nsec); - - /* One possibility is that the the elapsed time is greater than the - * time remaining in the time slice. This is a a race condition. It - * means that the timer has just expired. the interrupt will occu - * soon. - */ - - if (elapsed_ticks >= tcb->timeslice) - { - return; - } - - /* Otherwise, the unrealized time in this budget is the sum time slice - * value minus, the time from the unexpired timer. - */ - - tcb->timeslice -= (int32_t)elapsed_ticks; -#endif - - /* Handle any part of the budget that was not utilized. - * - * current = The initial budget at the beginning of the interval. - * tcb->timeslice = The unused part of that budget when the thread did - * not execute. - */ - - DEBUGASSERT(sporadic->active); - sporadic->active->unrealized = tcb->timeslice; - } + /* Save the time that the thread was suspended */ + sporadic->eventtime = clock_systimer(); return OK; } diff --git a/sched/sched/sched_suspendscheduler.c b/sched/sched/sched_suspendscheduler.c index e2d9a38bda0..16df6affb83 100644 --- a/sched/sched/sched_suspendscheduler.c +++ b/sched/sched/sched_suspendscheduler.c @@ -73,20 +73,9 @@ void sched_suspend_scheduler(FAR struct tcb_s *tcb) { - struct timespec suspend_time; - if ((tcb->flags & TCB_FLAG_POLICY_MASK) == TCB_FLAG_SCHED_SPORADIC) { -#ifdef CONFIG_SCHED_TICKLESS - /* Get the current time when the thread was suspended */ - - (void)up_timer_gettime(&suspend_time); -#else - suspend_time.tv_sec = 0; - suspend_time.tv_nsec = 0; -#endif - - DEBUGVERIFY(sched_sporadic_suspend(tcb, &suspend_time)); + DEBUGVERIFY(sched_sporadic_suspend(tcb)); } }