Add basic sporadic schedule state machine
This commit is contained in:
parent
3b1306078b
commit
ea7dbc984b
@ -52,6 +52,7 @@
|
||||
#include <time.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/wdog.h>
|
||||
#include <nuttx/mm/shm.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/net/net.h>
|
||||
@ -485,8 +486,10 @@ struct tcb_s
|
||||
uint8_t base_priority; /* "Normal" priority of the thread */
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_SPORADIC
|
||||
uint8_t hi_priority; /* Sporadic high priority */
|
||||
uint8_t low_priority; /* Sporadic low priority */
|
||||
uint8_t max_repl; /* Max. replenishments */
|
||||
uint8_t nrepl; /* Number replenishments remaining */
|
||||
#endif
|
||||
|
||||
uint8_t task_state; /* Current state of the thread */
|
||||
@ -494,16 +497,16 @@ struct tcb_s
|
||||
int16_t lockcount; /* 0=preemptable (not-locked) */
|
||||
|
||||
#if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_SPORADIC)
|
||||
int32_t timeslice; /* RR timeslice OR Sporadic */
|
||||
/* replenishment interval remaining */
|
||||
int32_t timeslice; /* RR timeslice OR Sporadic budget */
|
||||
/* interval remaining */
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_SPORADIC
|
||||
uint32_t spstart; /* Start time of execution budget */
|
||||
uint32_t repl_period; /* Sporadic replenishment period */
|
||||
uint32_t budget; /* Sporadic execution budget */
|
||||
struct wdog_s low_dog; /* Times low-priority interval */
|
||||
#endif
|
||||
|
||||
FAR struct wdog_s *waitdog; /* All timed waits used this wdog */
|
||||
FAR struct wdog_s *waitdog; /* All timed waits use this wdog */
|
||||
|
||||
/* Stack-Related Fields *******************************************************/
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sched.h>
|
||||
#include <queue.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <debug.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <queue.h>
|
||||
|
||||
@ -334,6 +335,7 @@ int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
|
||||
#ifdef CONFIG_SCHED_SPORADIC
|
||||
/* Save the sporadic scheduling parameters */
|
||||
|
||||
ptcb->cmn.hi_priority = priority;
|
||||
ptcb->cmn.low_priority = param.sched_ss_low_priority;
|
||||
ptcb->cmn.max_repl = param.sched_ss_max_repl;
|
||||
|
||||
@ -374,19 +376,15 @@ int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
|
||||
|
||||
/* Save the sporadic scheduling parameters */
|
||||
|
||||
ptcb->cmn.hi_priority = priority;
|
||||
ptcb->cmn.low_priority = attr->low_priority;
|
||||
ptcb->cmn.max_repl = attr->max_repl;
|
||||
ptcb->cmn.repl_period = repl_ticks;
|
||||
ptcb->cmn.budget = budget_ticks;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ignore sporadic scheduling parameters */
|
||||
|
||||
ptcb->cmn.low_priority = 0;
|
||||
ptcb->cmn.max_repl = 0;
|
||||
ptcb->cmn.repl_period = 0;
|
||||
ptcb->cmn.budget = 0;
|
||||
/* And start the frist replenishment interval */
|
||||
|
||||
DEBUGVERIFY(sched_sporadic_start(&ptcb->cmn));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -54,6 +54,10 @@ CSRCS += sched_waitid.c sched_wait.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SCHED_SPORADIC),y)
|
||||
CSRCS += sched_sporadic.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SCHED_CPULOAD),y)
|
||||
CSRCS += sched_cpuload.c
|
||||
endif
|
||||
|
@ -230,7 +230,6 @@ int sched_reprioritize(FAR struct tcb_s *tcb, int sched_priority);
|
||||
sched_setpriority(tcb,sched_priority)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_SCHED_TICKLESS
|
||||
unsigned int sched_timer_cancel(void);
|
||||
void sched_timer_resume(void);
|
||||
@ -241,6 +240,14 @@ void sched_timer_reassess(void);
|
||||
# define sched_timer_reassess()
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCHED_SPORADIC
|
||||
int sched_sporadic_start(FAR struct tcb_s *tcb);
|
||||
int sched_sporadic_stop(FAR struct tcb_s *tcb);
|
||||
int sched_sporadic_resume(FAR struct tcb_s *tcb);
|
||||
uint32_t sched_sporadic_process(FAR struct tcb_s *tcb, uint32_t,
|
||||
bool noswitches);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCHED_CPULOAD) && !defined(CONFIG_SCHED_CPULOAD_EXTCLK)
|
||||
void weak_function sched_process_cpuload(void);
|
||||
#endif
|
||||
|
@ -91,12 +91,12 @@
|
||||
*
|
||||
* Return Value:
|
||||
* On success, sched_setparam() returns 0 (OK). On error, -1
|
||||
* (ERROR) is returned, and errno is set appropriately.
|
||||
* (ERROR) is returned, and errno is set appropriately.
|
||||
*
|
||||
* EINVAL The parameter 'param' is invalid or does not make sense for the
|
||||
* current scheduling policy.
|
||||
* EPERM The calling task does not have appropriate privileges.
|
||||
* ESRCH The task whose ID is pid could not be found.
|
||||
* EINVAL The parameter 'param' is invalid or does not make sense for the
|
||||
* current scheduling policy.
|
||||
* EPERM The calling task does not have appropriate privileges.
|
||||
* ESRCH The task whose ID is pid could not be found.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
@ -124,6 +124,7 @@ int sched_reprioritize(FAR struct tcb_s *tcb, int sched_priority)
|
||||
tcb->npend_reprio = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_PRIORITY_INHERITANCE */
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sched.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
@ -130,6 +131,7 @@ int sched_setparam(pid_t pid, FAR const struct sched_param *param)
|
||||
|
||||
if ((rtcb->flags & TCB_FLAG_POLICY_MASK) == TCB_FLAG_SCHED_SPORADIC)
|
||||
{
|
||||
irqstate_t flags;
|
||||
int repl_ticks;
|
||||
int budget_ticks;
|
||||
|
||||
@ -150,17 +152,30 @@ int sched_setparam(pid_t pid, FAR const struct sched_param *param)
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
/* Save the sporadic scheduling parameters */
|
||||
/* Stop/reset current sporadic scheduling */
|
||||
|
||||
tcb->flags |= TCB_FLAG_SCHED_SPORADIC;
|
||||
tcb->timeslice = MSEC2TICK(CONFIG_RR_INTERVAL);
|
||||
flags = irqsave();
|
||||
DEBUGVERIFY(sched_sporadic_stop(tcb));
|
||||
|
||||
/* Save the sporadic scheduling parameters and reset to the beginning
|
||||
* to the replenishment interval.
|
||||
*/
|
||||
|
||||
tcb->timeslice = budget_ticks;
|
||||
tcb->hi_priority = param->sched_priority;
|
||||
tcb->low_priority = param->sched_ss_low_priority;
|
||||
tcb->max_repl = param->sched_ss_max_repl;
|
||||
tcb->repl_period = repl_ticks;
|
||||
tcb->budget = budget_ticks;
|
||||
|
||||
/* And restart at the next replenishment interval */
|
||||
|
||||
DEBUGVERIFY(sched_sporadic_start(tcb));
|
||||
irqrestore(flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
tcb->hi_priority = 0;
|
||||
tcb->low_priority = 0;
|
||||
tcb->max_repl = 0;
|
||||
tcb->repl_period = 0;
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
@ -135,15 +136,19 @@ int sched_setscheduler(pid_t pid, int policy,
|
||||
DEBUGPANIC();
|
||||
case SCHED_FIFO:
|
||||
{
|
||||
#ifdef CONFIG_SCHED_SPORADIC
|
||||
/* Cancel any on-going sporadic scheduling */
|
||||
|
||||
if ((tcb->flags & TCB_FLAG_POLICY_MASK) == TCB_FLAG_SCHED_SPORADIC)
|
||||
{
|
||||
DEBUGVERIFY(sched_sporadic_stop(tcb));
|
||||
}
|
||||
#endif
|
||||
/* Save the FIFO scheduling parameters */
|
||||
|
||||
tcb->flags |= TCB_FLAG_SCHED_FIFO;
|
||||
#if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_SPORADIC)
|
||||
tcb->timeslice = 0;
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_SPORADIC
|
||||
tcb->low_priority = 0;
|
||||
tcb->max_repl = 0;
|
||||
tcb->repl_period = 0;
|
||||
tcb->budget = 0;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
@ -151,14 +156,18 @@ int sched_setscheduler(pid_t pid, int policy,
|
||||
#if CONFIG_RR_INTERVAL > 0
|
||||
case SCHED_RR:
|
||||
{
|
||||
#ifdef CONFIG_SCHED_SPORADIC
|
||||
/* Cancel any on-going sporadic scheduling */
|
||||
|
||||
if ((tcb->flags & TCB_FLAG_POLICY_MASK) == TCB_FLAG_SCHED_SPORADIC)
|
||||
{
|
||||
DEBUGVERIFY(sched_sporadic_stop(tcb));
|
||||
}
|
||||
#endif
|
||||
/* Save the round robin scheduling parameters */
|
||||
|
||||
tcb->flags |= TCB_FLAG_SCHED_RR;
|
||||
tcb->timeslice = MSEC2TICK(CONFIG_RR_INTERVAL);
|
||||
#ifdef CONFIG_SCHED_SPORADIC
|
||||
tcb->low_priority = 0;
|
||||
tcb->max_repl = 0;
|
||||
tcb->repl_period = 0;
|
||||
tcb->budget = 0;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@ -183,18 +192,28 @@ int sched_setscheduler(pid_t pid, int policy,
|
||||
if (repl_ticks < budget_ticks)
|
||||
{
|
||||
set_errno(EINVAL);
|
||||
irqrestore(saved_state);
|
||||
sched_unlock();
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Save the sporadic scheduling parameters */
|
||||
/* Stop/reset current sporadic scheduling */
|
||||
|
||||
DEBUGVERIFY(sched_sporadic_stop(tcb));
|
||||
|
||||
/* Save the sporadic scheduling parameters. */
|
||||
|
||||
tcb->flags |= TCB_FLAG_SCHED_SPORADIC;
|
||||
tcb->timeslice = MSEC2TICK(CONFIG_RR_INTERVAL);
|
||||
tcb->timeslice = budget_ticks;
|
||||
tcb->hi_priority = param->sched_priority;
|
||||
tcb->low_priority = param->sched_ss_low_priority;
|
||||
tcb->max_repl = param->sched_ss_max_repl;
|
||||
tcb->repl_period = repl_ticks;
|
||||
tcb->budget = budget_ticks;
|
||||
|
||||
/* And restart at the next replenishment interval */
|
||||
|
||||
DEBUGVERIFY(sched_sporadic_start(tcb));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
436
sched/sched/sched_sporadic.c
Normal file
436
sched/sched/sched_sporadic.c
Normal file
@ -0,0 +1,436 @@
|
||||
/************************************************************************
|
||||
* sched/sched/sched_sporadic.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 <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/wdog.h>
|
||||
#include <nuttx/clock.h>
|
||||
|
||||
#include <arch/irq.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
|
||||
#ifdef CONFIG_SCHED_SPORADIC
|
||||
|
||||
/************************************************************************
|
||||
* Pre-processor Definitions
|
||||
************************************************************************/
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define MSEC20_TICKS MIN(MSEC2TICK(20),1)
|
||||
|
||||
/************************************************************************
|
||||
* Private Functions
|
||||
************************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Name: sched_sporadic_replenish_start
|
||||
*
|
||||
* Description:
|
||||
* Start the next replenishment cycle, increasing the priority of the
|
||||
* thread to the high priority. This is normally a pretty trivial
|
||||
* operation. But we do have to take a few precautions is priority
|
||||
* inheritance is enabled.
|
||||
*
|
||||
* Parameters:
|
||||
* tcb - TCB of the thread whose priority is being boosted.
|
||||
*
|
||||
* Return Value:
|
||||
* Returns zero (OK) on success or a negated errno value on failure.
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
static int sched_sporadic_replenish_start(FAR struct tcb_s *tcb)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Start the next replenishment interval */
|
||||
|
||||
tcb->timeslice = tcb->budget;
|
||||
tcb->nrepl = tcb->max_repl;
|
||||
|
||||
#ifdef CONFIG_PRIORITY_INHERITANCE
|
||||
/* If the priority was boosted above the higher priority, than just
|
||||
* reset the base priority.
|
||||
*/
|
||||
|
||||
if (tcb->sched_priority > tcb->base_priority)
|
||||
{
|
||||
/* Boosted... Do we still need to reprioritize? */
|
||||
|
||||
if (tcb->hi_priority < tcb->base_priority)
|
||||
{
|
||||
/* No.. the current execution priority is lower than the
|
||||
* boosted priority. Just reset the base priority.
|
||||
*/
|
||||
|
||||
tcb->base_priority = tcb->hi_priority;
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* The thread priority has not been boosted or it has been boosted to a
|
||||
* lower priority than the high priority. So, in either case, we need to
|
||||
* reset the priority.
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
/* Then reprioritize to the higher priority */
|
||||
|
||||
ret = sched_reprioritize(tcb, tcb->hi_priority);
|
||||
if (ret < 0)
|
||||
{
|
||||
return -get_errno();
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Name: sched_sporadic_expire
|
||||
*
|
||||
* Description:
|
||||
* Handles the expiration of a replenishment interval by starting the
|
||||
* next replenishment interval.
|
||||
*
|
||||
* Parameters:
|
||||
* Standard watchdog parameters
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* The thread is still running and is still using the sporadic
|
||||
* scheduling policy.
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
static void sched_sporadic_expire(int argc, wdparm_t arg1, ...)
|
||||
{
|
||||
FAR struct tcb_s *tcb = (FAR struct tcb_s *)arg1;
|
||||
|
||||
DEBUGASSERT(argc == 1 && tcb != NULL);
|
||||
|
||||
/* Start the next replenishment interval */
|
||||
|
||||
DEBUGVERIFY(sched_sporadic_replenish_start(tcb));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Functions
|
||||
************************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Name: sched_sporadic_start
|
||||
*
|
||||
* Description:
|
||||
* Called to initialize sporadic scheduling on a given thread. This
|
||||
* function is called in the following circumstances:
|
||||
*
|
||||
* - When starting a pthread with sporadic scheduling specified in
|
||||
* the pthread attributes.
|
||||
* - When establishing sporadic scheduling policy via
|
||||
* sched_setscheduler()
|
||||
* - When the sporadic scheduling parameters are changed via
|
||||
* sched_setparam().
|
||||
*
|
||||
* Parameters:
|
||||
* tcb - The TCB of the thread that is beginning sporadic scheduling.
|
||||
*
|
||||
* Return 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 thread is not currently using the sporadic scheduliing policy.
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
int sched_sporadic_start(FAR struct tcb_s *tcb)
|
||||
{
|
||||
DEBUGASSERT(tcb);
|
||||
|
||||
/* Cancel and pending low-priority interval timing and re-initialize
|
||||
* the watchdog timer.
|
||||
*/
|
||||
|
||||
wd_cancel(&tcb->low_dog);
|
||||
memset(&tcb->low_dog, 0, sizeof(struct wdog_s));
|
||||
|
||||
/* Then start the first replenishment interval */
|
||||
|
||||
return sched_sporadic_replenish_start(tcb);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Name: sched_sporadic_stop
|
||||
*
|
||||
* Description:
|
||||
* Called to terminate sporadic scheduling on a given thread. This
|
||||
* function is called in the following circumstances:
|
||||
*
|
||||
* - When any thread exits with sporadic scheduling active.
|
||||
* - When any thread using sporadic scheduling is changed to use
|
||||
* some other scheduling policy via sched_setscheduler()
|
||||
* - When the sporadic scheduling parameters are changed via
|
||||
* sched_setparam().
|
||||
*
|
||||
* Parameters:
|
||||
* tcb - The TCB of the thread that is beginning sporadic scheduling.
|
||||
*
|
||||
* Return 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 thread is currently using the sporadic scheduling policy.
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
int sched_sporadic_stop(FAR struct tcb_s *tcb)
|
||||
{
|
||||
DEBUGASSERT(tcb);
|
||||
|
||||
/* Cancel and pending low-priority interval timing and re-initialize
|
||||
* the watchdog timer.
|
||||
*/
|
||||
|
||||
wd_cancel(&tcb->low_dog);
|
||||
memset(&tcb->low_dog, 0, sizeof(struct wdog_s));
|
||||
|
||||
/* Reset sporadic scheduling parameters */
|
||||
|
||||
tcb->hi_priority = 0;
|
||||
tcb->low_priority = 0;
|
||||
tcb->max_repl = 0;
|
||||
tcb->nrepl = 0;
|
||||
tcb->timeslice = 0;
|
||||
tcb->repl_period = 0;
|
||||
tcb->budget = 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Name: sched_sporadic_replenish_resume
|
||||
*
|
||||
* Description:
|
||||
* Called to start the next replenishment interval. This function is
|
||||
* called in the following circumstances:
|
||||
*
|
||||
* - When a task using the sporadic scheduling policy is resumed
|
||||
* while in the budget interval of the replenishment cycle.
|
||||
*
|
||||
* Parameters:
|
||||
* tcb - The TCB of the thread that is beginning sporadic scheduling.
|
||||
*
|
||||
* Return 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
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
int sched_sporadic_replenish_resume(FAR struct tcb_s *tcb)
|
||||
{
|
||||
DEBUGASSERT(tcb);
|
||||
|
||||
/* Make sure that we are in the budget portion of the replenishment
|
||||
* interval. We know this is the case if the current timeslice is
|
||||
* non-zero. Do not exceed the maximum number of replenishments.
|
||||
*/
|
||||
|
||||
if (tcb->timeslice > 0 && tcb->nrepl > 0)
|
||||
{
|
||||
tcb->timeslice = tcb->budget;
|
||||
tcb->nrepl--;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Name: sched_sporadic_process
|
||||
*
|
||||
* Description:
|
||||
* Process the elapsed time interval. Called from this context:
|
||||
*
|
||||
* - From the timer interrupt handler while the thread with sporadic
|
||||
* scheduling is running.
|
||||
*
|
||||
* Parameters:
|
||||
* tcb - The TCB of the thread that is beginning sporadic scheduling.
|
||||
* ticks - The number of elapsed ticks since the last time this
|
||||
* function was called.
|
||||
*
|
||||
* Return Value:
|
||||
* The number if ticks remaining until the budget interval expires.
|
||||
* Zero is returned if we are in the low-prioriy phase of the the
|
||||
* replenishment interval.
|
||||
*
|
||||
* Assumptions:
|
||||
* - Interrupts are disabled
|
||||
* - All sporadic scheduling parameters in the TCB are valid
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
uint32_t sched_sporadic_process(FAR struct tcb_s *tcb, uint32_t ticks,
|
||||
bool noswitches)
|
||||
{
|
||||
DEBUGASSERT(tcb && ticks > 0);
|
||||
|
||||
/* If we are in the low-priority phase of the replenishment interval,
|
||||
* then just return zero.
|
||||
*/
|
||||
|
||||
if (tcb->timeslice <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if the the budget interval has elapse */
|
||||
|
||||
if (ticks >= tcb->timeslice)
|
||||
{
|
||||
/* Does the thread have the scheduler locked? */
|
||||
|
||||
if (tcb->lockcount > 0)
|
||||
{
|
||||
/* Yes... then we have no option but to give the thread more
|
||||
* time at the higher priority. Dropping the priority could
|
||||
* result in a context switch.
|
||||
*
|
||||
* Let then have up to 20 milliseconds (in ticks)
|
||||
*/
|
||||
|
||||
tcb->timeslice = MSEC20_TICKS;
|
||||
return MSEC20_TICKS;
|
||||
}
|
||||
|
||||
/* We will also suppress context switches if we were called via one of
|
||||
* the unusual cases handled by sched_timer_reasses(). In that case,
|
||||
* we will return a value of one so that the timer will expire as soon
|
||||
* as possible and we can perform this action in the normal timer
|
||||
* expiration context.
|
||||
*
|
||||
* This is kind of kludge, but I am not to concerned because I hope
|
||||
* that the situation is impossible or at least could only occur on
|
||||
* rare corner-cases.
|
||||
*/
|
||||
|
||||
if (noswitches)
|
||||
{
|
||||
tcb->timeslice = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Another possibility is the the budget interval is equal to the
|
||||
* entire replenishment interval. This would seem like such a good
|
||||
* thing to do, but is certainly permitted.
|
||||
*/
|
||||
|
||||
if (tcb->budget >= tcb->repl_period)
|
||||
{
|
||||
tcb->timeslice = tcb->budget;
|
||||
return tcb->budget;
|
||||
}
|
||||
|
||||
/* Otherwise enter the low-priority phase of the replenishment cycle */
|
||||
|
||||
tcb->timeslice = 0;
|
||||
|
||||
/* Start the timer that will terminate the low priority cycle. This timer
|
||||
* expiration is independent of what else may occur (except that it must
|
||||
* be cancelled if the thread exits.
|
||||
*/
|
||||
|
||||
DEBUGVERIFY(wd_start(&tcb->low_dog, tcb->repl_period - tcb->budget,
|
||||
sched_sporadic_expire, 1, (wdentry_t)tcb));
|
||||
|
||||
#ifdef CONFIG_PRIORITY_INHERITANCE
|
||||
/* If the priority was boosted above the higher priority, than just
|
||||
* reset the base priority.
|
||||
*/
|
||||
|
||||
if (tcb->sched_priority > tcb->base_priority)
|
||||
{
|
||||
/* Thread priority was boosted while we were in the high priority
|
||||
* state.
|
||||
*/
|
||||
|
||||
tcb->base_priority = tcb->low_priority;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Otherwise drop the priority of thread, possible causing a context
|
||||
* switch.
|
||||
*/
|
||||
|
||||
DEBUGVERIFY(sched_reprioritize(tcb, tcb->low_priority));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No.. then just decrement the time remaining in the budget interval
|
||||
* and continue.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
tcb->timeslice -= ticks;
|
||||
return tcb->timeslice;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SCHED_SPORADIC */
|
@ -63,6 +63,8 @@
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
struct tcb_s; /* Forward reference */
|
||||
|
||||
/* Task start-up */
|
||||
|
||||
void task_start(void);
|
||||
|
@ -39,6 +39,8 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/wdog.h>
|
||||
#include <nuttx/sched.h>
|
||||
@ -46,32 +48,9 @@
|
||||
#include "semaphore/semaphore.h"
|
||||
#include "wdog/wdog.h"
|
||||
#include "mqueue/mqueue.h"
|
||||
#include "sched/sched.h"
|
||||
#include "task/task.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Type Declarations
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Global Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -112,4 +91,13 @@ void task_recover(FAR struct tcb_s *tcb)
|
||||
|
||||
mq_recover(tcb);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SCHED_SPORADIC
|
||||
if ((tcb->flags & TCB_FLAG_POLICY_MASK) == TCB_FLAG_SCHED_SPORADIC)
|
||||
{
|
||||
/* Stop current sporadic scheduling */
|
||||
|
||||
DEBUGVERIFY(sched_sporadic_stop(tcb));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -44,6 +44,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <nuttx/compiler.h>
|
||||
#include <nuttx/wdog.h>
|
||||
|
@ -45,6 +45,8 @@
|
||||
#include <queue.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <arch/irq.h>
|
||||
|
||||
#include "timer/timer.h"
|
||||
|
||||
#ifndef CONFIG_DISABLE_POSIX_TIMERS
|
||||
|
@ -1,7 +1,7 @@
|
||||
/********************************************************************************
|
||||
* sched/wdog/wd_gettime.c
|
||||
*
|
||||
* Copyright (C) 2007, 2009, 2014 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2009, 2014-2015 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -40,6 +40,7 @@
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/wdog.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
#include "wdog/wdog.h"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user