Tickless Stuff: Back out the risky timer operations when the ready-to-run list is modified. That is unsafe. An ugly workaround is just to keep an interval timer going all of the time with a minimum duration equal to the timeslice interval.
This commit is contained in:
parent
eef608b942
commit
6546fa39c7
@ -119,4 +119,3 @@ void sched_addblocked(FAR struct tcb_s *btcb, tstate_t task_state)
|
||||
|
||||
btcb->task_state = task_state;
|
||||
}
|
||||
|
||||
|
@ -43,8 +43,6 @@
|
||||
#include <queue.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/clock.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
|
||||
/****************************************************************************
|
||||
@ -137,27 +135,6 @@ bool sched_addreadytorun(FAR struct tcb_s *btcb)
|
||||
|
||||
btcb->task_state = TSTATE_TASK_RUNNING;
|
||||
btcb->flink->task_state = TSTATE_TASK_READYTORUN;
|
||||
|
||||
#if CONFIG_RR_INTERVAL > 0
|
||||
/* Reset the round robin timeslice interval of both the old
|
||||
* and the new head of the ready-to-run list.
|
||||
*/
|
||||
|
||||
rtcb->timeslice = MSEC2TICK(CONFIG_RR_INTERVAL);
|
||||
btcb->timeslice = MSEC2TICK(CONFIG_RR_INTERVAL);
|
||||
|
||||
#if 0 /* REVISIT: This can cause crashes in certain cases */
|
||||
/* Whenever the task at the head of the ready-to-run changes, we
|
||||
* must reassess the interval time that controls time-slicing.
|
||||
*/
|
||||
|
||||
if ((rtcb->flags & TCB_FLAG_ROUND_ROBIN) != 0 ||
|
||||
(btcb->flags & TCB_FLAG_ROUND_ROBIN) != 0)
|
||||
{
|
||||
sched_timer_reassess();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
|
@ -43,8 +43,6 @@
|
||||
#include <queue.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/clock.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
|
||||
/****************************************************************************
|
||||
@ -112,40 +110,12 @@ bool sched_removereadytorun(FAR struct tcb_s *rtcb)
|
||||
|
||||
sched_note_switch(rtcb, ntcb);
|
||||
ntcb->task_state = TSTATE_TASK_RUNNING;
|
||||
|
||||
/* Remove the TCB from the head of the ready-to-run list */
|
||||
|
||||
(void)dq_remfirst((FAR dq_queue_t *)&g_readytorun);
|
||||
|
||||
#if CONFIG_RR_INTERVAL > 0
|
||||
/* Reset the round robin timeslice interval of the new head of the
|
||||
* ready-to-run list.
|
||||
*/
|
||||
|
||||
ntcb->timeslice = MSEC2TICK(CONFIG_RR_INTERVAL);
|
||||
|
||||
#if 0 /* REVISIT: This can cause crashes in certain cases */
|
||||
/* Whenever the task at the head of the ready-to-run changes, we
|
||||
* must reassess the interval time that controls time-slicing.
|
||||
*/
|
||||
|
||||
if ((rtcb->flags & TCB_FLAG_ROUND_ROBIN) != 0 ||
|
||||
(ntcb->flags & TCB_FLAG_ROUND_ROBIN) != 0)
|
||||
{
|
||||
sched_timer_reassess();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/* Indicate that a context switch is occurring */
|
||||
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove the TCB from the ready-to-run list (not from the head) */
|
||||
|
||||
dq_rem((FAR dq_entry_t *)rtcb, (FAR dq_queue_t *)&g_readytorun);
|
||||
}
|
||||
/* Remove the TCB from the ready-to-run list */
|
||||
|
||||
dq_rem((FAR dq_entry_t *)rtcb, (FAR dq_queue_t *)&g_readytorun);
|
||||
|
||||
/* Since the TCB is not in any list, it is now invalid */
|
||||
|
||||
|
@ -58,6 +58,22 @@
|
||||
/************************************************************************
|
||||
* Pre-processor Definitions
|
||||
************************************************************************/
|
||||
/* In the original design, it was planned that sched_timer_reasses() be
|
||||
* called whenever there was a change at the head of the ready-to-run
|
||||
* list. That call was intended to establish a new time-slice or to
|
||||
* stop an old time-slice timer. However, it turns out that that
|
||||
* solution is too fragile: The system is too vulnerable at the time
|
||||
* that the read-to-run list is modified in order to muck with timers.
|
||||
*
|
||||
* The kludge/work-around is simple to keep the timer running all of the
|
||||
* time with an interval of no more than the timeslice interface. If we
|
||||
* this, then there is really no need to do anything when on context
|
||||
* switches.
|
||||
*/
|
||||
|
||||
#if CONFIG_RR_INTERVAL > 0
|
||||
# define KEEP_ALIVE_HACK 1
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
@ -212,7 +228,11 @@ static unsigned int
|
||||
sched_process_timeslice(unsigned int ticks, bool noswitches)
|
||||
{
|
||||
FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head;
|
||||
#ifdef KEEP_ALIVE_HACK
|
||||
unsigned int ret = MSEC2TICK(CONFIG_RR_INTERVAL);
|
||||
#else
|
||||
unsigned int ret = 0;
|
||||
#endif
|
||||
int decr;
|
||||
|
||||
/* Check if the currently executing task uses round robin
|
||||
@ -293,13 +313,22 @@ sched_process_timeslice(unsigned int ticks, bool noswitches)
|
||||
*/
|
||||
|
||||
rtcb = (FAR struct tcb_s*)g_readytorun.head;
|
||||
|
||||
/* Check if the new task at the head of the ready-to-run
|
||||
* supports round robin scheduling.
|
||||
*/
|
||||
|
||||
if ((rtcb->flags & TCB_FLAG_ROUND_ROBIN) != 0)
|
||||
{
|
||||
/* The new task at the head of the ready to run
|
||||
* list does not support round robin scheduling.
|
||||
*/
|
||||
|
||||
#ifdef KEEP_ALIVE_HACK
|
||||
ret = MSEC2TICK(CONFIG_RR_INTERVAL);
|
||||
#else
|
||||
ret = 0;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user