Sporadic scheduler: Add logic to collection the partial timer expiration when a sporadic thread is suspended in tickless mode

This commit is contained in:
Gregory Nutt 2015-07-26 15:03:47 -06:00
parent 4bdbc387f5
commit 99664b7811
12 changed files with 466 additions and 129 deletions

28
TODO
View File

@ -1,4 +1,4 @@
NuttX TODO List (Last updated July 25, 2015)
NuttX TODO List (Last updated July 26, 2015)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with
@ -213,32 +213,6 @@ o Task/Scheduler (sched/)
Status: Open
Priority: Medium-ish
Title: TICKLESS SCHEDULING INACCURACIES
Description: Interval timers are set up to determine timing for round-
robin and sporadic scheduling policies. In the timer
interrupt mode, the budget remaining for the thread is
decremented on each timer interrupt and so is always
accurate to within one clock time. So when the task
suspended, the remaining budget is accurate.
But in tickless mode, the budget is only updated on the
expiration of the timer. So if the task is suspended by an
asynchronous event, the budget will fail to decrement and the
task will get a larger share of CPU that is deserves in those
cases.
UPDATE: The hook sched_suspend_scheduler() has been added to
all locations where a thread is suspended. This would be
the place to assess any partial intervals: You would have to
save the current time when the timer is started then when
suspended, you would have to assess the elapsed portion of
that time and subtract that from the TCB timeslice value.
The hook is present, but logic has been implemented.
Status: Open
Priority: Low. I am not aware of any real world issues.
o Memory Managment (mm/)
^^^^^^^^^^^^^^^^^^^^^^

View File

@ -274,6 +274,10 @@ struct sporadic_s
uint32_t current; /* Unrealized, current budget time */
uint32_t pending; /* Unrealized, pending execution budget */
#ifdef CONFIG_SCHED_TICKLESS
struct timespec sched_time; /* Time in ticks last processed */
#endif
/* This is the list of replenishment intervals */
struct replenishment_s replenishments[CONFIG_SCHED_SPORADIC_MAXREPL];
@ -804,9 +808,11 @@ void sched_resume_scheduler(FAR struct tcb_s *tcb);
*
********************************************************************************/
/* Just a place-holder for now */
#define sched_suspend_scheduler(tcb)
#if defined(CONFIG_SCHED_SPORADIC) && defined(CONFIG_SCHED_TICKLESS)
void sched_suspend_scheduler(FAR struct tcb_s *tcb);
#else
# define sched_suspend_scheduler(tcb)
#endif
#undef EXTERN
#if defined(__cplusplus)

View File

@ -35,7 +35,8 @@
CSRCS += clock_initialize.c clock_settime.c clock_gettime.c clock_getres.c
CSRCS += clock_time2ticks.c clock_abstime2ticks.c clock_ticks2time.c
CSRCS += clock_systimer.c clock_systimespec.c
CSRCS += clock_systimer.c clock_systimespec.c clock_timespec_add.c
CSRCS += clock_timespec_subtract.c
# Include clock build support

View File

@ -90,10 +90,16 @@ void weak_function clock_initialize(void);
void weak_function clock_timer(void);
#endif
int clock_abstime2ticks(clockid_t clockid,
FAR const struct timespec *abstime,
FAR int *ticks);
int clock_time2ticks(FAR const struct timespec *reltime, FAR int *ticks);
int clock_ticks2time(int ticks, FAR struct timespec *reltime);
int clock_abstime2ticks(clockid_t clockid,
FAR const struct timespec *abstime,
FAR int *ticks);
int clock_time2ticks(FAR const struct timespec *reltime, FAR int *ticks);
int clock_ticks2time(int ticks, FAR struct timespec *reltime);
void clock_timespec_add(FAR const struct timespec *ts1,
FAR const struct timespec *ts2,
FAR struct timespec *ts3);
void clock_timespec_subtract(FAR const struct timespec *ts1,
FAR const struct timespec *ts2,
FAR struct timespec *ts3);
#endif /* __SCHED_CLOCK_CLOCK_H */

View File

@ -0,0 +1,81 @@
/********************************************************************************
* sched/clock/clock_timespec_add.c
*
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
********************************************************************************/
/********************************************************************************
* Included Files
********************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <time.h>
#include "clock/clock.h"
/********************************************************************************
* Public Functions
********************************************************************************/
/************************************************************************
* Name: clock_timespec_add
*
* Description:
* Add timespec ts1 to to2 and return the result in ts3
*
* Inputs:
* ts1 and ts2: The two timespecs to be added
* t23: The location to return the result (may be ts1 or ts2)
*
* Return Value:
* None
*
************************************************************************/
void clock_timespec_add(FAR const struct timespec *ts1,
FAR const struct timespec *ts2,
FAR struct timespec *ts3)
{
time_t sec = ts1->tv_sec + ts2->tv_sec;
long nsec = ts1->tv_nsec + ts2->tv_nsec;
if (nsec >= NSEC_PER_SEC)
{
nsec -= NSEC_PER_SEC;
sec++;
}
ts3->tv_sec = sec;
ts3->tv_nsec = nsec;
}

View File

@ -0,0 +1,100 @@
/********************************************************************************
* sched/clock/clock_timespec_subtract.c
*
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
********************************************************************************/
/********************************************************************************
* Included Files
********************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <time.h>
#include "clock/clock.h"
/********************************************************************************
* Public Functions
********************************************************************************/
/************************************************************************
* Name: clock_timespec_subtract
*
* Description:
* Subtract timespec ts2 from to1 and return the result in ts3.
* Zero is returned if the time difference is negative.
*
* Inputs:
* ts1 and ts2: The two timespecs to be subtracted (ts1 - ts2)
* t23: The location to return the result (may be ts1 or ts2)
*
* Return Value:
* None
*
************************************************************************/
void clock_timespec_subtract(FAR const struct timespec *ts1,
FAR const struct timespec *ts2,
FAR struct timespec *ts3)
{
time_t sec;
long nsec;
if (ts1->tv_sec < ts2->tv_sec)
{
sec = 0;
nsec = 0;
}
else if (ts1->tv_sec == ts2->tv_sec && ts1->tv_nsec <= ts2->tv_nsec)
{
sec = 0;
nsec = 0;
}
else
{
sec = ts1->tv_sec + ts2->tv_sec;
if (ts1->tv_nsec < ts2->tv_nsec)
{
nsec = (ts1->tv_nsec + NSEC_PER_SEC) - ts2->tv_nsec;
sec--;
}
else
{
nsec = ts1->tv_nsec - ts2->tv_nsec;
}
}
ts3->tv_sec = sec;
ts3->tv_nsec = nsec;
}

View File

@ -70,6 +70,12 @@ CSRCS += sched_resumescheduler.c
endif
endif
ifeq ($(CONFIG_SCHED_TICKLESS),y)
ifeq ($(CONFIG_SCHED_SPORADIC),y)
CSRCS += sched_suspendscheduler.c
endif
endif
ifeq ($(CONFIG_SCHED_CPULOAD),y)
CSRCS += sched_cpuload.c
endif

View File

@ -251,6 +251,10 @@ 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);
#ifdef CONFIG_SCHED_TICKLESS
int sched_sporadic_suspend(FAR struct tcb_s *tcb,
FAR const struct timespec *suspend_time);
#endif
uint32_t sched_sporadic_process(FAR struct tcb_s *tcb, uint32_t ticks,
bool noswitches);
void sched_sporadic_lowpriority(FAR struct tcb_s *tcb);

View File

@ -75,10 +75,7 @@ void sched_resume_scheduler(FAR struct tcb_s *tcb)
if ((tcb->flags & TCB_FLAG_POLICY_MASK) == TCB_FLAG_SCHED_RR)
#endif
{
/* Reset its timeslice. This is only meaningful for round robin tasks but
* it doesn't here to do it for everything (as long as CONFIG_SCHED_SPORADIC
* is not defined.
*/
/* Reset the task's timeslice. */
tcb->timeslice = MSEC2TICK(CONFIG_RR_INTERVAL);
}

View File

@ -51,6 +51,7 @@
#include <arch/irq.h>
#include "clock/clock.h"
#include "sched/sched.h"
#ifdef CONFIG_SCHED_SPORADIC
@ -114,6 +115,14 @@ static int sporadic_budget_start(FAR struct tcb_s *tcb,
tcb->timeslice = budget;
sporadic->current = budget;
#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 */
ret = wd_start(&repl->timer, budget, sporadic_budget_expire, 1,
(wdentry_t)repl);
@ -806,9 +815,108 @@ int sched_sporadic_resume(FAR struct tcb_s *tcb)
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;
}
/****************************************************************************
* Name: sched_sporadic_suspend
*
* Description:
* Called to when a thread with sporadic scheduling is suspended in the
* tickless mode. In this case, there is unaccounted for time from the
* time that the last interval timer was started up until this point.
*
* This function calculates the elpased time since then, and adjusts the
* timeslice time accordingly.
*
* Input Parameters:
* tcb - The TCB of the thread that is beginning sporadic scheduling.
* suspend_time - The time that the thread was suspended.
*
* Returned Value:
* 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
*
****************************************************************************/
#ifdef CONFIG_SCHED_TICKLESS
int sched_sporadic_suspend(FAR struct tcb_s *tcb,
FAR const struct timespec *suspend_time)
{
FAR struct sporadic_s *sporadic;
struct timespec elapsed_time;
uint32_t elapsed_ticks;
DEBUGASSERT(tcb && tcb->sporadic);
sporadic = tcb->sporadic;
/* 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 && tcb->timeslice < sporadic->current)
{
/* Get the difference in time between the time that the scheduler just
* ran and time time that the thread was spuspended. 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.
*
* Ideally, we would need to cancel the budget time and start the low-
* priority portion of the interval. But we are in a precarious
* situation here.. The TCB has been removed from the ready to run
* list already so we cannot use the normal reprioritization logic.
*/
if (elapsed_ticks >= tcb->timeslice)
{
/* REVISIT: The kludge here is to just set the clock to one tick.
* That will cause the interval to expire very quickly.
*/
tcb->timeslice = 1;
}
else
{
tcb->timeslice -= (int32_t)elapsed_ticks;
}
}
return OK;
}
#endif
/****************************************************************************
* Name: sched_sporadic_process
*

View File

@ -0,0 +1,87 @@
/****************************************************************************
* sched/sched/sched_suspendscheduler.c
*
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <time.h>
#include <assert.h>
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include <nuttx/clock.h>
#include "clock/clock.h"
#include "sched/sched.h"
#if defined(CONFIG_SCHED_SPORADIC) && defined(CONFIG_SCHED_TICKLESS)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sched_suspend_scheduler
*
* Description:
* Called by architecture specific implementations that starts task
* execution. This function prepares the scheduler for the thread that is
* about to be restarted.
*
* Input Parameters:
* tcb - The TCB of the thread that is being suspended.
*
* Returned Value:
* None
*
****************************************************************************/
void sched_suspend_scheduler(FAR struct tcb_s *tcb)
{
struct timespec suspend_time;
if ((tcb->flags & TCB_FLAG_POLICY_MASK) == TCB_FLAG_SCHED_SPORADIC)
{
/* Get the current time when the thread was suspended */
(void)up_timer_gettime(&suspend_time);
DEBUGVERIFY(sched_sporadic_suspend(tcb, &suspend_time));
}
}
#endif /* CONFIG_SCHED_SPORADIC && CONFIG_SCHED_TICKLESS */

View File

@ -118,6 +118,12 @@ uint32_t g_oneshot_maxticks = UINT32_MAX;
static unsigned int g_timer_interval;
#ifdef CONFIG_SCHED_SPORADIC
/* This is the time of the last scheduler assessment */
static struct timespec g_sched_time;
#endif
#ifdef CONFIG_SCHED_TICKLESS_ALARM
/* This is the time that the timer was stopped. All future times are
* calculated against this time. It must be valid at all times when
@ -130,92 +136,6 @@ static struct timespec g_stop_time;
/************************************************************************
* Private Functions
************************************************************************/
/************************************************************************
* Name: sched_timespec_add
*
* Description:
* Add timespec ts1 to to2 and return the result in ts3
*
* Inputs:
* ts1 and ts2: The two timespecs to be added
* t23: The location to return the result (may be ts1 or ts2)
*
* Return Value:
* None
*
************************************************************************/
#ifdef CONFIG_SCHED_TICKLESS_ALARM
static void sched_timespec_add(FAR const struct timespec *ts1,
FAR const struct timespec *ts2,
FAR struct timespec *ts3)
{
time_t sec = ts1->tv_sec + ts2->tv_sec;
long nsec = ts1->tv_nsec + ts2->tv_nsec;
if (nsec >= NSEC_PER_SEC)
{
nsec -= NSEC_PER_SEC;
sec++;
}
ts3->tv_sec = sec;
ts3->tv_nsec = nsec;
}
#endif
/************************************************************************
* Name: sched_timespec_subtract
*
* Description:
* Subtract timespec ts2 from to1 and return the result in ts3.
* Zero is returned if the time difference is negative.
*
* Inputs:
* ts1 and ts2: The two timespecs to be subtracted (ts1 - ts2)
* t23: The location to return the result (may be ts1 or ts2)
*
* Return Value:
* None
*
************************************************************************/
#ifdef CONFIG_SCHED_TICKLESS_ALARM
static void sched_timespec_subtract(FAR const struct timespec *ts1,
FAR const struct timespec *ts2,
FAR struct timespec *ts3)
{
time_t sec;
long nsec;
if (ts1->tv_sec < ts2->tv_sec)
{
sec = 0;
nsec = 0;
}
else if (ts1->tv_sec == ts2->tv_sec && ts1->tv_nsec <= ts2->tv_nsec)
{
sec = 0;
nsec = 0;
}
else
{
sec = ts1->tv_sec + ts2->tv_sec;
if (ts1->tv_nsec < ts2->tv_nsec)
{
nsec = (ts1->tv_nsec + NSEC_PER_SEC) - ts2->tv_nsec;
sec--;
}
else
{
nsec = ts1->tv_nsec - ts2->tv_nsec;
}
}
ts3->tv_sec = sec;
ts3->tv_nsec = nsec;
}
#endif
/************************************************************************
* Name: sched_process_scheduler
@ -261,11 +181,25 @@ static inline uint32_t sched_process_scheduler(uint32_t ticks, bool noswitches)
}
#endif
#if CONFIG_RR_INTERVAL > 0
#ifdef CONFIG_SCHED_SPORADIC
/* Check if the currently executing task uses sporadic scheduling. */
if ((rtcb->flags & TCB_FLAG_POLICY_MASK) == TCB_FLAG_SCHED_SPORADIC)
{
FAR struct sporadic_s *sporadic = rtcb->sporadic;
DEBUGASSERT(sporadic);
/* Save the last time that the scheduler ran. This time was saved
* higher in the calling hierarchy but cannot be applied until here.
* That is because there are cases that context switches may occur
* between then and before we get here. So we can't positive of
* which task TCB to save the time in until we are here and
* committed to updating the scheduler for this TCB.
*/
sporadic->sched_time.tv_sec = g_sched_time.tv_sec;
sporadic->sched_time.tv_nsec = g_sched_time.tv_nsec;
/* Yes, check if the currently executing task has exceeded its
* budget.
*/
@ -417,7 +351,7 @@ static void sched_timer_start(unsigned int ticks)
* to the time when last stopped the timer).
*/
sched_timespec_add(&g_stop_time, &ts, &ts);
clock_timespec_add(&g_stop_time, &ts, &ts);
ret = up_alarm_start(&ts);
#else
@ -471,6 +405,13 @@ void sched_alarm_expiration(FAR const struct timespec *ts)
g_stop_time.tv_sec = ts->tv_sec;
g_stop_time.tv_nsec = ts->tv_nsec;
#ifdef CONFIG_SCHED_SPORADIC
/* Save the last time that the scheduler ran */
g_sched_time.tv_sec = ts->tv_sec;
g_sched_time.tv_nsec = ts->tv_nsec;
#endif
/* Get the interval associated with last expiration */
elapsed = g_timer_interval;
@ -510,6 +451,12 @@ void sched_timer_expiration(void)
elapsed = g_timer_interval;
g_timer_interval = 0;
#ifdef CONFIG_SCHED_SPORADIC
/* Save the last time that the scheduler ran */
(void)up_timer_gettime(&g_sched_time);
#endif
/* Process the timer ticks and set up the next interval (or not) */
nexttime = sched_timer_process(elapsed, false);
@ -558,9 +505,16 @@ unsigned int sched_timer_cancel(void)
(void)up_alarm_cancel(&g_stop_time);
#ifdef CONFIG_SCHED_SPORADIC
/* Save the last time that the scheduler ran */
g_sched_time.tv_sec = g_stop_time.tv_sec;
g_sched_time.tv_nsec = g_stop_time.tv_nsec;
#endif
/* Convert this to the elapsed time */
sched_timespec_subtract(&g_stop_time, &ts, &ts);
clock_timespec_subtract(&g_stop_time, &ts, &ts);
/* Convert to ticks */
@ -582,6 +536,13 @@ unsigned int sched_timer_cancel(void)
(void)up_timer_cancel(&ts);
#ifdef CONFIG_SCHED_SPORADIC
/* Save the last time that the scheduler ran */
g_sched_time.tv_sec = ts.tv_sec;
g_sched_time.tv_nsec = ts.tv_nsec;
#endif
/* Convert to ticks */
ticks = SEC2TICK(ts.tv_sec);
@ -628,6 +589,12 @@ void sched_timer_resume(void)
{
unsigned int nexttime;
#ifdef CONFIG_SCHED_SPORADIC
/* Save the last time that the scheduler ran */
(void)up_timer_gettime(&g_sched_time);
#endif
/* Reassess the next deadline (by simply processing a zero ticks expired)
* and set up the next interval (or not).
*/