Fixes several more sporadic scheduler bugs
This commit is contained in:
parent
a7322f5a6d
commit
95ca3a1d1e
@ -267,6 +267,7 @@ struct replenishment_s
|
|||||||
|
|
||||||
struct sporadic_s
|
struct sporadic_s
|
||||||
{
|
{
|
||||||
|
bool suspended; /* Thread is currently suspended */
|
||||||
uint8_t hi_priority; /* Sporadic high priority */
|
uint8_t hi_priority; /* Sporadic high priority */
|
||||||
uint8_t low_priority; /* Sporadic low priority */
|
uint8_t low_priority; /* Sporadic low priority */
|
||||||
uint8_t max_repl; /* Maximum number of replenishments */
|
uint8_t max_repl; /* Maximum number of replenishments */
|
||||||
|
@ -77,6 +77,7 @@ static int sporadic_set_lowpriority(FAR struct tcb_s *tcb);
|
|||||||
static int sporadic_interval_start(FAR struct replenishment_s *repl);
|
static int sporadic_interval_start(FAR struct replenishment_s *repl);
|
||||||
static void sporadic_budget_expire(int argc, wdparm_t arg1, ...);
|
static void sporadic_budget_expire(int argc, wdparm_t arg1, ...);
|
||||||
static void sporadic_interval_expire(int argc, wdparm_t arg1, ...);
|
static void sporadic_interval_expire(int argc, wdparm_t arg1, ...);
|
||||||
|
static void sporadic_timer_cancel(FAR struct tcb_s *tcb);
|
||||||
FAR struct replenishment_s *
|
FAR struct replenishment_s *
|
||||||
sporadic_alloc_repl(FAR struct sporadic_s *sporadic);
|
sporadic_alloc_repl(FAR struct sporadic_s *sporadic);
|
||||||
|
|
||||||
@ -187,21 +188,11 @@ static int sporadic_budget_start(FAR struct tcb_s *tcb,
|
|||||||
repl->budget = budget;
|
repl->budget = budget;
|
||||||
repl->unrealized = 0;
|
repl->unrealized = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_SCHED_TICKLESS
|
|
||||||
/* Save the time that the replenishment interval started */
|
|
||||||
|
|
||||||
(void)up_timer_gettime(&sporadic->sched_time);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* And start the timer for the budget interval */
|
/* And start the timer for the budget interval */
|
||||||
|
|
||||||
DEBUGVERIFY(wd_start(&repl->timer, budget, sporadic_budget_expire, 1,
|
DEBUGVERIFY(wd_start(&repl->timer, budget, sporadic_budget_expire, 1,
|
||||||
(wdentry_t)repl));
|
(wdentry_t)repl));
|
||||||
|
|
||||||
/* Save the time that the thread was started */
|
|
||||||
|
|
||||||
sporadic->eventtime = clock_systimer();
|
|
||||||
|
|
||||||
/* Then reprioritize to the higher priority */
|
/* Then reprioritize to the higher priority */
|
||||||
|
|
||||||
return sporadic_set_hipriority(tcb);
|
return sporadic_set_hipriority(tcb);
|
||||||
@ -439,12 +430,9 @@ static void sporadic_budget_expire(int argc, wdparm_t arg1, ...)
|
|||||||
|
|
||||||
tcb->timeslice = -1;
|
tcb->timeslice = -1;
|
||||||
|
|
||||||
/* Cancel and free the timer */
|
/* Cancel and free all timers */
|
||||||
|
|
||||||
wd_cancel(&repl->timer);
|
sporadic_timer_cancel(tcb);
|
||||||
repl->budget = 0;
|
|
||||||
repl->active = false;
|
|
||||||
sporadic->nrepls--;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -664,6 +652,11 @@ int sched_sporadic_start(FAR struct tcb_s *tcb)
|
|||||||
repl = sporadic_alloc_repl(sporadic);
|
repl = sporadic_alloc_repl(sporadic);
|
||||||
DEBUGASSERT(repl != NULL && sporadic->nrepls == 1);
|
DEBUGASSERT(repl != NULL && sporadic->nrepls == 1);
|
||||||
|
|
||||||
|
/* Save the time that the scheduler was started */
|
||||||
|
|
||||||
|
sporadic->eventtime = clock_systimer();
|
||||||
|
sporadic->suspended = true;
|
||||||
|
|
||||||
/* Then start the first interval */
|
/* Then start the first interval */
|
||||||
|
|
||||||
return sporadic_budget_start(tcb, repl, sporadic->budget);
|
return sporadic_budget_start(tcb, repl, sporadic->budget);
|
||||||
@ -762,6 +755,7 @@ int sched_sporadic_reset(FAR struct tcb_s *tcb)
|
|||||||
|
|
||||||
/* Reset sporadic scheduling parameters and state data */
|
/* Reset sporadic scheduling parameters and state data */
|
||||||
|
|
||||||
|
sporadic->suspended = true;
|
||||||
sporadic->hi_priority = 0;
|
sporadic->hi_priority = 0;
|
||||||
sporadic->low_priority = 0;
|
sporadic->low_priority = 0;
|
||||||
sporadic->max_repl = 0;
|
sporadic->max_repl = 0;
|
||||||
@ -784,7 +778,7 @@ int sched_sporadic_reset(FAR struct tcb_s *tcb)
|
|||||||
* using the sporadic scheduling policy.
|
* using the sporadic scheduling policy.
|
||||||
*
|
*
|
||||||
* This function does nothing if the budget phase as already elapsed or
|
* This function does nothing if the budget phase as already elapsed or
|
||||||
* the maximum numer of replenishments have already been performed.
|
* the maximum number of replenishments have already been performed.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* tcb - The TCB of the thread that is beginning sporadic scheduling.
|
* tcb - The TCB of the thread that is beginning sporadic scheduling.
|
||||||
@ -810,26 +804,36 @@ int sched_sporadic_resume(FAR struct tcb_s *tcb)
|
|||||||
DEBUGASSERT(tcb && tcb->sporadic);
|
DEBUGASSERT(tcb && tcb->sporadic);
|
||||||
sporadic = tcb->sporadic;
|
sporadic = tcb->sporadic;
|
||||||
|
|
||||||
|
/* If we are resumed more than one, ignore all but the first */
|
||||||
|
|
||||||
|
if (!sporadic->suspended)
|
||||||
|
{
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the first time */
|
||||||
|
|
||||||
|
sporadic->suspended = false;
|
||||||
|
|
||||||
#ifdef CONFIG_SPORADIC_INSTRUMENTATION
|
#ifdef CONFIG_SPORADIC_INSTRUMENTATION
|
||||||
/* Inform the monitor of this event */
|
/* Inform the monitor of this event */
|
||||||
|
|
||||||
arch_sporadic_resume(tcb);
|
arch_sporadic_resume(tcb);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Get the time that the thread was [re-]started */
|
||||||
|
|
||||||
|
now = clock_systimer();
|
||||||
|
|
||||||
/* Check if are in the budget portion of the replenishment interval. We
|
/* Check if are in the budget portion of the replenishment interval. We
|
||||||
* know this is the case if the current timeslice is non-zero.
|
* know this is the case if the current timeslice is non-zero.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb->timeslice > 0)
|
if (tcb->timeslice > 0)
|
||||||
{
|
{
|
||||||
/* Save the time that the thread was [re-]started */
|
|
||||||
|
|
||||||
now = clock_systimer();
|
|
||||||
|
|
||||||
/* Unrealized budget time while the thread was suspended */
|
/* Unrealized budget time while the thread was suspended */
|
||||||
|
|
||||||
unrealized = sporadic->eventtime - now;
|
unrealized = now - sporadic->eventtime;
|
||||||
sporadic->eventtime = now;
|
|
||||||
|
|
||||||
/* Ignore very short pre-emptions that are below our timing resolution. */
|
/* Ignore very short pre-emptions that are below our timing resolution. */
|
||||||
|
|
||||||
@ -837,10 +841,10 @@ int sched_sporadic_resume(FAR struct tcb_s *tcb)
|
|||||||
{
|
{
|
||||||
/* Handle any part of the budget that was not utilized.
|
/* Handle any part of the budget that was not utilized.
|
||||||
*
|
*
|
||||||
* current = The initial budget at the beginning of the
|
* current = The initial budget at the beginning of the
|
||||||
* interval.
|
* interval.
|
||||||
* urealized = The unused part of that budget when the
|
* unrealized = The unused part of that budget when the
|
||||||
* thread did not execute.
|
* thread did not execute.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (unrealized >= tcb->timeslice)
|
if (unrealized >= tcb->timeslice)
|
||||||
@ -848,11 +852,10 @@ int sched_sporadic_resume(FAR struct tcb_s *tcb)
|
|||||||
/* We lost the remainder of the timeslice, (and then some).
|
/* We lost the remainder of the timeslice, (and then some).
|
||||||
* No point in starting more timers.
|
* No point in starting more timers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGASSERT(sporadic->active);
|
DEBUGASSERT(sporadic->active);
|
||||||
tcb->timeslice -= unrealized;
|
tcb->timeslice -= unrealized;
|
||||||
sporadic->active->unrealized = unrealized;
|
sporadic->active->unrealized = unrealized;
|
||||||
|
|
||||||
@ -888,6 +891,7 @@ int sched_sporadic_resume(FAR struct tcb_s *tcb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sporadic->eventtime = now;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -895,25 +899,17 @@ int sched_sporadic_resume(FAR struct tcb_s *tcb)
|
|||||||
* Name: sched_sporadic_suspend
|
* Name: sched_sporadic_suspend
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Called to when a thread with sporadic scheduling is suspended in the
|
* Called to when a thread with sporadic scheduling is suspended. In this
|
||||||
* tickless mode. In this case, there is unaccounted for time from the
|
* case, there will be unaccounted for time from the time that the last
|
||||||
* time that the last interval timer was started up until this point.
|
* when the task is resumed. All that we need to do here is remember
|
||||||
*
|
* that time that we were suspended.
|
||||||
* This function calculates the elapsed time since then, and adjusts the
|
|
||||||
* timeslice time accordingly.
|
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* tcb - The TCB of the thread that is beginning sporadic scheduling.
|
* tcb - The TCB of the thread that is beginning sporadic scheduling.
|
||||||
* suspend_time - The time that the thread was suspended.
|
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Returns zero (OK) on success or a negated errno value on failure.
|
* Returns zero (OK) on success or a negated errno value on failure.
|
||||||
*
|
*
|
||||||
* Assumptions:
|
|
||||||
* - Interrupts are disabled
|
|
||||||
* - All sporadic scheduling parameters in the TCB are valid
|
|
||||||
* - The low priority interval timer is not running
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int sched_sporadic_suspend(FAR struct tcb_s *tcb)
|
int sched_sporadic_suspend(FAR struct tcb_s *tcb)
|
||||||
@ -923,15 +919,25 @@ int sched_sporadic_suspend(FAR struct tcb_s *tcb)
|
|||||||
DEBUGASSERT(tcb && tcb->sporadic);
|
DEBUGASSERT(tcb && tcb->sporadic);
|
||||||
sporadic = tcb->sporadic;
|
sporadic = tcb->sporadic;
|
||||||
|
|
||||||
#ifdef CONFIG_SPORADIC_INSTRUMENTATION
|
/* If we are suspended more than one, ignore all but the first */
|
||||||
/* Inform the monitor of this event */
|
|
||||||
|
|
||||||
arch_sporadic_suspend(tcb);
|
if (!sporadic->suspended)
|
||||||
|
{
|
||||||
|
/* This is the first time */
|
||||||
|
|
||||||
|
sporadic->suspended = true;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SPORADIC_INSTRUMENTATION
|
||||||
|
/* Inform the monitor of this event */
|
||||||
|
|
||||||
|
arch_sporadic_suspend(tcb);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Save the time that the thread was suspended */
|
/* Save the time that the thread was suspended */
|
||||||
|
|
||||||
|
sporadic->eventtime = clock_systimer();
|
||||||
|
}
|
||||||
|
|
||||||
sporadic->eventtime = clock_systimer();
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1028,7 +1034,7 @@ uint32_t sched_sporadic_process(FAR struct tcb_s *tcb, uint32_t ticks,
|
|||||||
|
|
||||||
if (noswitches)
|
if (noswitches)
|
||||||
{
|
{
|
||||||
tcb->timeslice = 1;
|
tcb->timeslice = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1043,9 +1049,10 @@ uint32_t sched_sporadic_process(FAR struct tcb_s *tcb, uint32_t ticks,
|
|||||||
return sporadic->budget;
|
return sporadic->budget;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise enter the low-priority phase of the replenishment cycle */
|
/* Otherwise enter the low-priority phase of the replenishment cycle.
|
||||||
|
* Let the timers handle the priority changes.
|
||||||
|
*/
|
||||||
|
|
||||||
sporadic_set_lowpriority(tcb);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1104,7 +1111,11 @@ void sched_sporadic_lowpriority(FAR struct tcb_s *tcb)
|
|||||||
DEBUGASSERT(sporadic->nrepls < sporadic->max_repl);
|
DEBUGASSERT(sporadic->nrepls < sporadic->max_repl);
|
||||||
repl = sporadic_alloc_repl(sporadic);
|
repl = sporadic_alloc_repl(sporadic);
|
||||||
DEBUGASSERT(repl != NULL);
|
DEBUGASSERT(repl != NULL);
|
||||||
repl->budget = sporadic->budget;
|
|
||||||
|
tcb->timeslice = 0;
|
||||||
|
sporadic->active = repl;
|
||||||
|
repl->budget = sporadic->budget;
|
||||||
|
repl->unrealized = 0;
|
||||||
|
|
||||||
/* Drop the priority of thread, possible causing a context switch. */
|
/* Drop the priority of thread, possible causing a context switch. */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user