mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 03:45:50 +08:00
Add basic sporadic schedule state machine
This commit is contained in:
@@ -52,6 +52,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include <nuttx/irq.h>
|
#include <nuttx/irq.h>
|
||||||
|
#include <nuttx/wdog.h>
|
||||||
#include <nuttx/mm/shm.h>
|
#include <nuttx/mm/shm.h>
|
||||||
#include <nuttx/fs/fs.h>
|
#include <nuttx/fs/fs.h>
|
||||||
#include <nuttx/net/net.h>
|
#include <nuttx/net/net.h>
|
||||||
@@ -485,8 +486,10 @@ struct tcb_s
|
|||||||
uint8_t base_priority; /* "Normal" priority of the thread */
|
uint8_t base_priority; /* "Normal" priority of the thread */
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SCHED_SPORADIC
|
#ifdef CONFIG_SCHED_SPORADIC
|
||||||
|
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; /* Max. replenishments */
|
uint8_t max_repl; /* Max. replenishments */
|
||||||
|
uint8_t nrepl; /* Number replenishments remaining */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t task_state; /* Current state of the thread */
|
uint8_t task_state; /* Current state of the thread */
|
||||||
@@ -494,16 +497,16 @@ struct tcb_s
|
|||||||
int16_t lockcount; /* 0=preemptable (not-locked) */
|
int16_t lockcount; /* 0=preemptable (not-locked) */
|
||||||
|
|
||||||
#if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_SPORADIC)
|
#if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_SPORADIC)
|
||||||
int32_t timeslice; /* RR timeslice OR Sporadic */
|
int32_t timeslice; /* RR timeslice OR Sporadic budget */
|
||||||
/* replenishment interval remaining */
|
/* interval remaining */
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SCHED_SPORADIC
|
#ifdef CONFIG_SCHED_SPORADIC
|
||||||
uint32_t spstart; /* Start time of execution budget */
|
|
||||||
uint32_t repl_period; /* Sporadic replenishment period */
|
uint32_t repl_period; /* Sporadic replenishment period */
|
||||||
uint32_t budget; /* Sporadic execution budget */
|
uint32_t budget; /* Sporadic execution budget */
|
||||||
|
struct wdog_s low_dog; /* Times low-priority interval */
|
||||||
#endif
|
#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 *******************************************************/
|
/* Stack-Related Fields *******************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sched.h>
|
#include <queue.h>
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <queue.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
|
#ifdef CONFIG_SCHED_SPORADIC
|
||||||
/* Save the sporadic scheduling parameters */
|
/* Save the sporadic scheduling parameters */
|
||||||
|
|
||||||
|
ptcb->cmn.hi_priority = priority;
|
||||||
ptcb->cmn.low_priority = param.sched_ss_low_priority;
|
ptcb->cmn.low_priority = param.sched_ss_low_priority;
|
||||||
ptcb->cmn.max_repl = param.sched_ss_max_repl;
|
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 */
|
/* Save the sporadic scheduling parameters */
|
||||||
|
|
||||||
|
ptcb->cmn.hi_priority = priority;
|
||||||
ptcb->cmn.low_priority = attr->low_priority;
|
ptcb->cmn.low_priority = attr->low_priority;
|
||||||
ptcb->cmn.max_repl = attr->max_repl;
|
ptcb->cmn.max_repl = attr->max_repl;
|
||||||
ptcb->cmn.repl_period = repl_ticks;
|
ptcb->cmn.repl_period = repl_ticks;
|
||||||
ptcb->cmn.budget = budget_ticks;
|
ptcb->cmn.budget = budget_ticks;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Ignore sporadic scheduling parameters */
|
|
||||||
|
|
||||||
ptcb->cmn.low_priority = 0;
|
/* And start the frist replenishment interval */
|
||||||
ptcb->cmn.max_repl = 0;
|
|
||||||
ptcb->cmn.repl_period = 0;
|
DEBUGVERIFY(sched_sporadic_start(&ptcb->cmn));
|
||||||
ptcb->cmn.budget = 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ CSRCS += sched_waitid.c sched_wait.c
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_SCHED_SPORADIC),y)
|
||||||
|
CSRCS += sched_sporadic.c
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_SCHED_CPULOAD),y)
|
ifeq ($(CONFIG_SCHED_CPULOAD),y)
|
||||||
CSRCS += sched_cpuload.c
|
CSRCS += sched_cpuload.c
|
||||||
endif
|
endif
|
||||||
|
|||||||
+8
-1
@@ -230,7 +230,6 @@ int sched_reprioritize(FAR struct tcb_s *tcb, int sched_priority);
|
|||||||
sched_setpriority(tcb,sched_priority)
|
sched_setpriority(tcb,sched_priority)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_SCHED_TICKLESS
|
#ifdef CONFIG_SCHED_TICKLESS
|
||||||
unsigned int sched_timer_cancel(void);
|
unsigned int sched_timer_cancel(void);
|
||||||
void sched_timer_resume(void);
|
void sched_timer_resume(void);
|
||||||
@@ -241,6 +240,14 @@ void sched_timer_reassess(void);
|
|||||||
# define sched_timer_reassess()
|
# define sched_timer_reassess()
|
||||||
#endif
|
#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)
|
#if defined(CONFIG_SCHED_CPULOAD) && !defined(CONFIG_SCHED_CPULOAD_EXTCLK)
|
||||||
void weak_function sched_process_cpuload(void);
|
void weak_function sched_process_cpuload(void);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -91,12 +91,12 @@
|
|||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
* On success, sched_setparam() returns 0 (OK). On error, -1
|
* 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
|
* EINVAL The parameter 'param' is invalid or does not make sense for the
|
||||||
* current scheduling policy.
|
* current scheduling policy.
|
||||||
* EPERM The calling task does not have appropriate privileges.
|
* EPERM The calling task does not have appropriate privileges.
|
||||||
* ESRCH The task whose ID is pid could not be found.
|
* ESRCH The task whose ID is pid could not be found.
|
||||||
*
|
*
|
||||||
* Assumptions:
|
* Assumptions:
|
||||||
*
|
*
|
||||||
@@ -124,6 +124,7 @@ int sched_reprioritize(FAR struct tcb_s *tcb, int sched_priority)
|
|||||||
tcb->npend_reprio = 0;
|
tcb->npend_reprio = 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PRIORITY_INHERITANCE */
|
#endif /* CONFIG_PRIORITY_INHERITANCE */
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include <nuttx/arch.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)
|
if ((rtcb->flags & TCB_FLAG_POLICY_MASK) == TCB_FLAG_SCHED_SPORADIC)
|
||||||
{
|
{
|
||||||
|
irqstate_t flags;
|
||||||
int repl_ticks;
|
int repl_ticks;
|
||||||
int budget_ticks;
|
int budget_ticks;
|
||||||
|
|
||||||
@@ -150,17 +152,30 @@ int sched_setparam(pid_t pid, FAR const struct sched_param *param)
|
|||||||
goto errout_with_lock;
|
goto errout_with_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the sporadic scheduling parameters */
|
/* Stop/reset current sporadic scheduling */
|
||||||
|
|
||||||
tcb->flags |= TCB_FLAG_SCHED_SPORADIC;
|
flags = irqsave();
|
||||||
tcb->timeslice = MSEC2TICK(CONFIG_RR_INTERVAL);
|
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->low_priority = param->sched_ss_low_priority;
|
||||||
tcb->max_repl = param->sched_ss_max_repl;
|
tcb->max_repl = param->sched_ss_max_repl;
|
||||||
tcb->repl_period = repl_ticks;
|
tcb->repl_period = repl_ticks;
|
||||||
tcb->budget = budget_ticks;
|
tcb->budget = budget_ticks;
|
||||||
|
|
||||||
|
/* And restart at the next replenishment interval */
|
||||||
|
|
||||||
|
DEBUGVERIFY(sched_sporadic_start(tcb));
|
||||||
|
irqrestore(flags);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
tcb->hi_priority = 0;
|
||||||
tcb->low_priority = 0;
|
tcb->low_priority = 0;
|
||||||
tcb->max_repl = 0;
|
tcb->max_repl = 0;
|
||||||
tcb->repl_period = 0;
|
tcb->repl_period = 0;
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
@@ -135,15 +136,19 @@ int sched_setscheduler(pid_t pid, int policy,
|
|||||||
DEBUGPANIC();
|
DEBUGPANIC();
|
||||||
case SCHED_FIFO:
|
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;
|
tcb->flags |= TCB_FLAG_SCHED_FIFO;
|
||||||
#if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_SPORADIC)
|
#if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_SPORADIC)
|
||||||
tcb->timeslice = 0;
|
tcb->timeslice = 0;
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_SCHED_SPORADIC
|
|
||||||
tcb->low_priority = 0;
|
|
||||||
tcb->max_repl = 0;
|
|
||||||
tcb->repl_period = 0;
|
|
||||||
tcb->budget = 0;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -151,14 +156,18 @@ int sched_setscheduler(pid_t pid, int policy,
|
|||||||
#if CONFIG_RR_INTERVAL > 0
|
#if CONFIG_RR_INTERVAL > 0
|
||||||
case SCHED_RR:
|
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->flags |= TCB_FLAG_SCHED_RR;
|
||||||
tcb->timeslice = MSEC2TICK(CONFIG_RR_INTERVAL);
|
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;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@@ -183,18 +192,28 @@ int sched_setscheduler(pid_t pid, int policy,
|
|||||||
if (repl_ticks < budget_ticks)
|
if (repl_ticks < budget_ticks)
|
||||||
{
|
{
|
||||||
set_errno(EINVAL);
|
set_errno(EINVAL);
|
||||||
|
irqrestore(saved_state);
|
||||||
sched_unlock();
|
sched_unlock();
|
||||||
return ERROR;
|
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->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->low_priority = param->sched_ss_low_priority;
|
||||||
tcb->max_repl = param->sched_ss_max_repl;
|
tcb->max_repl = param->sched_ss_max_repl;
|
||||||
tcb->repl_period = repl_ticks;
|
tcb->repl_period = repl_ticks;
|
||||||
tcb->budget = budget_ticks;
|
tcb->budget = budget_ticks;
|
||||||
|
|
||||||
|
/* And restart at the next replenishment interval */
|
||||||
|
|
||||||
|
DEBUGVERIFY(sched_sporadic_start(tcb));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct tcb_s; /* Forward reference */
|
||||||
|
|
||||||
/* Task start-up */
|
/* Task start-up */
|
||||||
|
|
||||||
void task_start(void);
|
void task_start(void);
|
||||||
|
|||||||
+12
-24
@@ -39,6 +39,8 @@
|
|||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
#include <nuttx/wdog.h>
|
#include <nuttx/wdog.h>
|
||||||
#include <nuttx/sched.h>
|
#include <nuttx/sched.h>
|
||||||
@@ -46,32 +48,9 @@
|
|||||||
#include "semaphore/semaphore.h"
|
#include "semaphore/semaphore.h"
|
||||||
#include "wdog/wdog.h"
|
#include "wdog/wdog.h"
|
||||||
#include "mqueue/mqueue.h"
|
#include "mqueue/mqueue.h"
|
||||||
|
#include "sched/sched.h"
|
||||||
#include "task/task.h"
|
#include "task/task.h"
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Pre-processor Definitions
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Type Declarations
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Global Variables
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Variables
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Function Prototypes
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Functions
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -112,4 +91,13 @@ void task_recover(FAR struct tcb_s *tcb)
|
|||||||
|
|
||||||
mq_recover(tcb);
|
mq_recover(tcb);
|
||||||
#endif
|
#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 <sys/types.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include <nuttx/compiler.h>
|
#include <nuttx/compiler.h>
|
||||||
#include <nuttx/wdog.h>
|
#include <nuttx/wdog.h>
|
||||||
|
|||||||
@@ -45,6 +45,8 @@
|
|||||||
#include <queue.h>
|
#include <queue.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <arch/irq.h>
|
||||||
|
|
||||||
#include "timer/timer.h"
|
#include "timer/timer.h"
|
||||||
|
|
||||||
#ifndef CONFIG_DISABLE_POSIX_TIMERS
|
#ifndef CONFIG_DISABLE_POSIX_TIMERS
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* sched/wdog/wd_gettime.c
|
* 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>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <nuttx/wdog.h>
|
#include <nuttx/wdog.h>
|
||||||
|
#include <arch/irq.h>
|
||||||
|
|
||||||
#include "wdog/wdog.h"
|
#include "wdog/wdog.h"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user