forked from Imagelibrary/rtems
score: Rework EDF scheduler
Use inline red-black tree insert. Do not use shifting priorities since this is not supported by the thread queues. Due to the 32-bit Priority_Control this currently limits the uptime to 49days with a 1ms clock tick. Update #2173.
This commit is contained in:
@@ -35,7 +35,7 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
/**@{*/
|
/**@{*/
|
||||||
|
|
||||||
#define SCHEDULER_EDF_MAXIMUM_PRIORITY 255
|
#define SCHEDULER_EDF_MAXIMUM_PRIORITY 0x7fffffff
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry points for the Earliest Deadline First Scheduler.
|
* Entry points for the Earliest Deadline First Scheduler.
|
||||||
@@ -81,18 +81,6 @@ typedef struct {
|
|||||||
RBTree_Control Ready;
|
RBTree_Control Ready;
|
||||||
} Scheduler_EDF_Context;
|
} Scheduler_EDF_Context;
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef Scheduler_EDF_Queue_state
|
|
||||||
*
|
|
||||||
* This enumeration distiguishes state of a thread with respect to the
|
|
||||||
* ready queue.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
SCHEDULER_EDF_QUEUE_STATE_NOT_PRESENTLY,
|
|
||||||
SCHEDULER_EDF_QUEUE_STATE_YES,
|
|
||||||
SCHEDULER_EDF_QUEUE_STATE_NEVER_HAS_BEEN
|
|
||||||
} Scheduler_EDF_Queue_state;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Scheduler node specialization for EDF schedulers.
|
* @brief Scheduler node specialization for EDF schedulers.
|
||||||
*/
|
*/
|
||||||
@@ -110,10 +98,17 @@ typedef struct {
|
|||||||
* Rbtree node related to this thread.
|
* Rbtree node related to this thread.
|
||||||
*/
|
*/
|
||||||
RBTree_Node Node;
|
RBTree_Node Node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State of the thread with respect to ready queue.
|
* @brief The thread priority used by this scheduler instance in case no job
|
||||||
|
* is released.
|
||||||
*/
|
*/
|
||||||
Scheduler_EDF_Queue_state queue_state;
|
Priority_Control background_priority;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The thread priority currently used by this scheduler instance.
|
||||||
|
*/
|
||||||
|
Priority_Control current_priority;
|
||||||
} Scheduler_EDF_Node;
|
} Scheduler_EDF_Node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -44,44 +44,92 @@ RTEMS_INLINE_ROUTINE Scheduler_EDF_Node *_Scheduler_EDF_Thread_get_node(
|
|||||||
return (Scheduler_EDF_Node *) _Scheduler_Thread_get_node( the_thread );
|
return (Scheduler_EDF_Node *) _Scheduler_Thread_get_node( the_thread );
|
||||||
}
|
}
|
||||||
|
|
||||||
int _Scheduler_EDF_Priority_compare (
|
RTEMS_INLINE_ROUTINE bool _Scheduler_EDF_Less(
|
||||||
Priority_Control p1,
|
const void *left,
|
||||||
Priority_Control p2
|
const RBTree_Node *right
|
||||||
);
|
|
||||||
|
|
||||||
RBTree_Compare_result _Scheduler_EDF_Compare(
|
|
||||||
const RBTree_Node* n1,
|
|
||||||
const RBTree_Node* n2
|
|
||||||
);
|
|
||||||
|
|
||||||
RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Enqueue(
|
|
||||||
const Scheduler_Control *scheduler,
|
|
||||||
Thread_Control *the_thread
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Scheduler_EDF_Context *context =
|
const Priority_Control *the_left;
|
||||||
_Scheduler_EDF_Get_context( scheduler );
|
const Scheduler_EDF_Node *the_right;
|
||||||
Scheduler_EDF_Node *node = _Scheduler_EDF_Thread_get_node( the_thread );
|
Priority_Control prio_left;
|
||||||
|
Priority_Control prio_right;
|
||||||
|
|
||||||
_RBTree_Insert(
|
the_left = left;
|
||||||
|
the_right = RTEMS_CONTAINER_OF( right, Scheduler_EDF_Node, Node );
|
||||||
|
|
||||||
|
prio_left = *the_left;
|
||||||
|
prio_right = the_right->current_priority;
|
||||||
|
|
||||||
|
return prio_left < prio_right;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTEMS_INLINE_ROUTINE bool _Scheduler_EDF_Less_or_equal(
|
||||||
|
const void *left,
|
||||||
|
const RBTree_Node *right
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const Priority_Control *the_left;
|
||||||
|
const Scheduler_EDF_Node *the_right;
|
||||||
|
Priority_Control prio_left;
|
||||||
|
Priority_Control prio_right;
|
||||||
|
|
||||||
|
the_left = left;
|
||||||
|
the_right = RTEMS_CONTAINER_OF( right, Scheduler_EDF_Node, Node );
|
||||||
|
|
||||||
|
prio_left = *the_left;
|
||||||
|
prio_right = the_right->current_priority;
|
||||||
|
|
||||||
|
return prio_left <= prio_right;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Enqueue(
|
||||||
|
Scheduler_EDF_Context *context,
|
||||||
|
Scheduler_EDF_Node *node,
|
||||||
|
Priority_Control current_priority
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_RBTree_Insert_inline(
|
||||||
&context->Ready,
|
&context->Ready,
|
||||||
&node->Node,
|
&node->Node,
|
||||||
_Scheduler_EDF_Compare,
|
¤t_priority,
|
||||||
false
|
_Scheduler_EDF_Less
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Enqueue_first(
|
||||||
|
Scheduler_EDF_Context *context,
|
||||||
|
Scheduler_EDF_Node *node,
|
||||||
|
Priority_Control current_priority
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_RBTree_Insert_inline(
|
||||||
|
&context->Ready,
|
||||||
|
&node->Node,
|
||||||
|
¤t_priority,
|
||||||
|
_Scheduler_EDF_Less_or_equal
|
||||||
);
|
);
|
||||||
node->queue_state = SCHEDULER_EDF_QUEUE_STATE_YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Extract(
|
RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Extract(
|
||||||
|
Scheduler_EDF_Context *context,
|
||||||
|
Scheduler_EDF_Node *node
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_RBTree_Extract( &context->Ready, &node->Node );
|
||||||
|
}
|
||||||
|
|
||||||
|
RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Extract_body(
|
||||||
const Scheduler_Control *scheduler,
|
const Scheduler_Control *scheduler,
|
||||||
Thread_Control *the_thread
|
Thread_Control *the_thread
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Scheduler_EDF_Context *context =
|
Scheduler_EDF_Context *context;
|
||||||
_Scheduler_EDF_Get_context( scheduler );
|
Scheduler_EDF_Node *node;
|
||||||
Scheduler_EDF_Node *node = _Scheduler_EDF_Thread_get_node( the_thread );
|
|
||||||
|
|
||||||
_RBTree_Extract( &context->Ready, &node->Node );
|
context = _Scheduler_EDF_Get_context( scheduler );
|
||||||
|
node = _Scheduler_EDF_Thread_get_node( the_thread );
|
||||||
|
|
||||||
|
_Scheduler_EDF_Extract( context, node );
|
||||||
}
|
}
|
||||||
|
|
||||||
RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Schedule_body(
|
RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Schedule_body(
|
||||||
@@ -90,16 +138,17 @@ RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Schedule_body(
|
|||||||
bool force_dispatch
|
bool force_dispatch
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Scheduler_EDF_Context *context =
|
Scheduler_EDF_Context *context;
|
||||||
_Scheduler_EDF_Get_context( scheduler );
|
RBTree_Node *first;
|
||||||
RBTree_Node *first = _RBTree_Minimum( &context->Ready );
|
Scheduler_EDF_Node *node;
|
||||||
Scheduler_EDF_Node *node =
|
|
||||||
RTEMS_CONTAINER_OF( first, Scheduler_EDF_Node, Node );
|
|
||||||
Thread_Control *heir = node->thread;
|
|
||||||
|
|
||||||
( void ) the_thread;
|
(void) the_thread;
|
||||||
|
|
||||||
_Scheduler_Update_heir( heir, force_dispatch );
|
context = _Scheduler_EDF_Get_context( scheduler );
|
||||||
|
first = _RBTree_Minimum( &context->Ready );
|
||||||
|
node = RTEMS_CONTAINER_OF( first, Scheduler_EDF_Node, Node );
|
||||||
|
|
||||||
|
_Scheduler_Update_heir( node->thread, force_dispatch );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**@}*/
|
/**@}*/
|
||||||
|
|||||||
@@ -25,13 +25,10 @@ void _Scheduler_CBS_Node_initialize(
|
|||||||
Thread_Control *the_thread
|
Thread_Control *the_thread
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Scheduler_CBS_Node *node = _Scheduler_CBS_Thread_get_node( the_thread );
|
Scheduler_CBS_Node *node;
|
||||||
|
|
||||||
(void) scheduler;
|
_Scheduler_EDF_Node_initialize( scheduler, the_thread );
|
||||||
|
|
||||||
_Scheduler_Node_do_initialize( &node->Base.Base, the_thread );
|
node = _Scheduler_CBS_Thread_get_node( the_thread );
|
||||||
|
|
||||||
node->Base.thread = the_thread;
|
|
||||||
node->Base.queue_state = SCHEDULER_EDF_QUEUE_STATE_NEVER_HAS_BEEN;
|
|
||||||
node->cbs_server = NULL;
|
node->cbs_server = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,12 +30,15 @@ Scheduler_Void_or_thread _Scheduler_CBS_Unblock(
|
|||||||
Thread_Control *the_thread
|
Thread_Control *the_thread
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Scheduler_CBS_Node *node = _Scheduler_CBS_Thread_get_node( the_thread );
|
Scheduler_EDF_Context *context;
|
||||||
Scheduler_CBS_Server *serv_info = node->cbs_server;
|
Scheduler_CBS_Node *node;
|
||||||
Priority_Control new_priority;
|
Scheduler_CBS_Server *serv_info;
|
||||||
|
Priority_Control priority;
|
||||||
|
|
||||||
_Scheduler_EDF_Enqueue( scheduler, the_thread );
|
context = _Scheduler_EDF_Get_context( scheduler );
|
||||||
/* TODO: flash critical section? */
|
node = _Scheduler_CBS_Thread_get_node( the_thread );
|
||||||
|
serv_info = node->cbs_server;
|
||||||
|
priority = node->Base.current_priority;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Late unblock rule for deadline-driven tasks. The remaining time to
|
* Late unblock rule for deadline-driven tasks. The remaining time to
|
||||||
@@ -43,29 +46,30 @@ Scheduler_Void_or_thread _Scheduler_CBS_Unblock(
|
|||||||
* without increased utilization of this task. It might cause a deadline
|
* without increased utilization of this task. It might cause a deadline
|
||||||
* miss of another task.
|
* miss of another task.
|
||||||
*/
|
*/
|
||||||
if (serv_info) {
|
if ( serv_info != NULL && ( priority & SCHEDULER_EDF_PRIO_MSB ) == 0 ) {
|
||||||
time_t deadline = serv_info->parameters.deadline;
|
time_t deadline = serv_info->parameters.deadline;
|
||||||
time_t budget = serv_info->parameters.budget;
|
time_t budget = serv_info->parameters.budget;
|
||||||
time_t deadline_left = the_thread->cpu_time_budget;
|
uint32_t deadline_left = the_thread->cpu_time_budget;
|
||||||
time_t budget_left = the_thread->real_priority -
|
Priority_Control budget_left = priority - _Watchdog_Ticks_since_boot;
|
||||||
_Watchdog_Ticks_since_boot;
|
|
||||||
|
|
||||||
if ( deadline*budget_left > budget*deadline_left ) {
|
if ( deadline * budget_left > budget * deadline_left ) {
|
||||||
/* Put late unblocked task to background until the end of period. */
|
/* Put late unblocked task to background until the end of period. */
|
||||||
new_priority = the_thread->Start.initial_priority;
|
|
||||||
the_thread->real_priority = new_priority;
|
priority = node->Base.background_priority;
|
||||||
if ( the_thread->current_priority != new_priority ) {
|
the_thread->real_priority = priority;
|
||||||
the_thread->current_priority = new_priority;
|
|
||||||
_Scheduler_EDF_Change_priority(
|
if (
|
||||||
scheduler,
|
_Thread_Priority_less_than( the_thread->current_priority, priority )
|
||||||
the_thread,
|
|| !_Thread_Owns_resources( the_thread )
|
||||||
new_priority,
|
) {
|
||||||
true
|
the_thread->current_priority = priority;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node->Base.current_priority = priority;
|
||||||
|
_Scheduler_EDF_Enqueue( context, &node->Base, priority );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the thread that was unblocked is more important than the heir,
|
* If the thread that was unblocked is more important than the heir,
|
||||||
* then we have a new heir. This may or may not result in a
|
* then we have a new heir. This may or may not result in a
|
||||||
@@ -78,16 +82,8 @@ Scheduler_Void_or_thread _Scheduler_CBS_Unblock(
|
|||||||
* Even if the thread isn't preemptible, if the new heir is
|
* Even if the thread isn't preemptible, if the new heir is
|
||||||
* a pseudo-ISR system task, we need to do a context switch.
|
* a pseudo-ISR system task, we need to do a context switch.
|
||||||
*/
|
*/
|
||||||
if (
|
if ( priority < _Thread_Heir->current_priority ) {
|
||||||
_Scheduler_EDF_Priority_compare(
|
_Scheduler_Update_heir( the_thread, priority == PRIORITY_PSEUDO_ISR );
|
||||||
the_thread->current_priority,
|
|
||||||
_Thread_Heir->current_priority
|
|
||||||
) == 1
|
|
||||||
) {
|
|
||||||
_Scheduler_Update_heir(
|
|
||||||
the_thread,
|
|
||||||
the_thread->current_priority == PRIORITY_PSEUDO_ISR
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SCHEDULER_RETURN_VOID_OR_NULL;
|
SCHEDULER_RETURN_VOID_OR_NULL;
|
||||||
|
|||||||
@@ -20,47 +20,6 @@
|
|||||||
|
|
||||||
#include <rtems/score/scheduleredfimpl.h>
|
#include <rtems/score/scheduleredfimpl.h>
|
||||||
|
|
||||||
int _Scheduler_EDF_Priority_compare (
|
|
||||||
Priority_Control p1,
|
|
||||||
Priority_Control p2
|
|
||||||
)
|
|
||||||
{
|
|
||||||
Watchdog_Interval time = _Watchdog_Ticks_since_boot;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reorder priorities to separate deadline driven and background tasks.
|
|
||||||
*
|
|
||||||
* The background tasks have p1 or p2 > SCHEDULER_EDF_PRIO_MSB.
|
|
||||||
* The deadline driven tasks need to have subtracted current time in order
|
|
||||||
* to see which deadline is closer wrt. current time.
|
|
||||||
*/
|
|
||||||
if (!(p1 & SCHEDULER_EDF_PRIO_MSB))
|
|
||||||
p1 = (p1 - time) & ~SCHEDULER_EDF_PRIO_MSB;
|
|
||||||
if (!(p2 & SCHEDULER_EDF_PRIO_MSB))
|
|
||||||
p2 = (p2 - time) & ~SCHEDULER_EDF_PRIO_MSB;
|
|
||||||
|
|
||||||
return ((p1<p2) - (p1>p2));
|
|
||||||
}
|
|
||||||
|
|
||||||
RBTree_Compare_result _Scheduler_EDF_Compare(
|
|
||||||
const RBTree_Node* n1,
|
|
||||||
const RBTree_Node* n2
|
|
||||||
)
|
|
||||||
{
|
|
||||||
Scheduler_EDF_Node *edf1 =
|
|
||||||
RTEMS_CONTAINER_OF( n1, Scheduler_EDF_Node, Node );
|
|
||||||
Scheduler_EDF_Node *edf2 =
|
|
||||||
RTEMS_CONTAINER_OF( n2, Scheduler_EDF_Node, Node );
|
|
||||||
Priority_Control value1 = edf1->thread->current_priority;
|
|
||||||
Priority_Control value2 = edf2->thread->current_priority;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function compares only numbers for the red-black tree,
|
|
||||||
* but priorities have an opposite sense.
|
|
||||||
*/
|
|
||||||
return (-1)*_Scheduler_EDF_Priority_compare(value1, value2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _Scheduler_EDF_Initialize( const Scheduler_Control *scheduler )
|
void _Scheduler_EDF_Initialize( const Scheduler_Control *scheduler )
|
||||||
{
|
{
|
||||||
Scheduler_EDF_Context *context =
|
Scheduler_EDF_Context *context =
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ void _Scheduler_EDF_Block(
|
|||||||
_Scheduler_Generic_block(
|
_Scheduler_Generic_block(
|
||||||
scheduler,
|
scheduler,
|
||||||
the_thread,
|
the_thread,
|
||||||
_Scheduler_EDF_Extract,
|
_Scheduler_EDF_Extract_body,
|
||||||
_Scheduler_EDF_Schedule_body
|
_Scheduler_EDF_Schedule_body
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,17 +43,25 @@ Scheduler_Void_or_thread _Scheduler_EDF_Change_priority(
|
|||||||
bool prepend_it
|
bool prepend_it
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Scheduler_EDF_Context *context =
|
Scheduler_EDF_Context *context;
|
||||||
_Scheduler_EDF_Get_context( scheduler );
|
Scheduler_EDF_Node *node;
|
||||||
Scheduler_EDF_Node *node = _Scheduler_EDF_Thread_get_node( the_thread );
|
|
||||||
|
|
||||||
_RBTree_Extract( &context->Ready, &node->Node );
|
context = _Scheduler_EDF_Get_context( scheduler );
|
||||||
_RBTree_Insert(
|
node = _Scheduler_EDF_Thread_get_node( the_thread );
|
||||||
&context->Ready,
|
|
||||||
&node->Node,
|
if ( ( new_priority & SCHEDULER_EDF_PRIO_MSB ) != 0 ) {
|
||||||
_Scheduler_EDF_Compare,
|
node->background_priority = new_priority;
|
||||||
false
|
}
|
||||||
);
|
|
||||||
|
node->current_priority = new_priority;
|
||||||
|
|
||||||
|
_Scheduler_EDF_Extract( context, node );
|
||||||
|
|
||||||
|
if ( prepend_it ) {
|
||||||
|
_Scheduler_EDF_Enqueue_first( context, node, new_priority );
|
||||||
|
} else {
|
||||||
|
_Scheduler_EDF_Enqueue( context, node, new_priority );
|
||||||
|
}
|
||||||
|
|
||||||
_Scheduler_EDF_Schedule_body( scheduler, the_thread, false );
|
_Scheduler_EDF_Schedule_body( scheduler, the_thread, false );
|
||||||
|
|
||||||
|
|||||||
@@ -32,5 +32,4 @@ void _Scheduler_EDF_Node_initialize(
|
|||||||
_Scheduler_Node_do_initialize( &node->Base, the_thread );
|
_Scheduler_Node_do_initialize( &node->Base, the_thread );
|
||||||
|
|
||||||
node->thread = the_thread;
|
node->thread = the_thread;
|
||||||
node->queue_state = SCHEDULER_EDF_QUEUE_STATE_NEVER_HAS_BEEN;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,33 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <rtems/score/scheduleredf.h>
|
#include <rtems/score/scheduleredfimpl.h>
|
||||||
#include <rtems/score/threadimpl.h>
|
|
||||||
#include <rtems/score/watchdogimpl.h>
|
static bool _Scheduler_EDF_Priority_filter(
|
||||||
|
Thread_Control *the_thread,
|
||||||
|
Priority_Control *new_priority_p,
|
||||||
|
void *arg
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Scheduler_EDF_Node *node;
|
||||||
|
Priority_Control current_priority;
|
||||||
|
Priority_Control new_priority;
|
||||||
|
|
||||||
|
node = _Scheduler_EDF_Thread_get_node( the_thread );
|
||||||
|
|
||||||
|
current_priority = the_thread->current_priority;
|
||||||
|
new_priority = *new_priority_p;
|
||||||
|
|
||||||
|
if ( new_priority == 0 ) {
|
||||||
|
new_priority = node->background_priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->current_priority = new_priority;
|
||||||
|
the_thread->real_priority = new_priority;
|
||||||
|
|
||||||
|
return _Thread_Priority_less_than( current_priority, new_priority )
|
||||||
|
|| !_Thread_Owns_resources( the_thread );
|
||||||
|
}
|
||||||
|
|
||||||
void _Scheduler_EDF_Release_job(
|
void _Scheduler_EDF_Release_job(
|
||||||
const Scheduler_Control *scheduler,
|
const Scheduler_Control *scheduler,
|
||||||
@@ -28,19 +52,11 @@ void _Scheduler_EDF_Release_job(
|
|||||||
uint64_t deadline
|
uint64_t deadline
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Priority_Control new_priority;
|
_Thread_Change_priority(
|
||||||
Priority_Control unused;
|
the_thread,
|
||||||
|
(Priority_Control) deadline,
|
||||||
(void) scheduler;
|
NULL,
|
||||||
|
_Scheduler_EDF_Priority_filter,
|
||||||
if (deadline) {
|
true
|
||||||
/* Initializing or shifting deadline. */
|
);
|
||||||
new_priority = (uint32_t) deadline & ~SCHEDULER_EDF_PRIO_MSB;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Switch back to background priority. */
|
|
||||||
new_priority = the_thread->Start.initial_priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
_Thread_Set_priority( the_thread, new_priority, &unused, true );
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,13 @@ Scheduler_Void_or_thread _Scheduler_EDF_Unblock(
|
|||||||
Thread_Control *the_thread
|
Thread_Control *the_thread
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_Scheduler_EDF_Enqueue( scheduler, the_thread );
|
Scheduler_EDF_Context *context;
|
||||||
/* TODO: flash critical section? */
|
Scheduler_EDF_Node *node;
|
||||||
|
|
||||||
|
context = _Scheduler_EDF_Get_context( scheduler );
|
||||||
|
node = _Scheduler_EDF_Thread_get_node( the_thread );
|
||||||
|
|
||||||
|
_Scheduler_EDF_Enqueue( context, node, node->current_priority );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the thread that was unblocked is more important than the heir,
|
* If the thread that was unblocked is more important than the heir,
|
||||||
@@ -42,12 +47,7 @@ Scheduler_Void_or_thread _Scheduler_EDF_Unblock(
|
|||||||
* Even if the thread isn't preemptible, if the new heir is
|
* Even if the thread isn't preemptible, if the new heir is
|
||||||
* a pseudo-ISR system task, we need to do a context switch.
|
* a pseudo-ISR system task, we need to do a context switch.
|
||||||
*/
|
*/
|
||||||
if (
|
if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
|
||||||
_Scheduler_EDF_Priority_compare(
|
|
||||||
the_thread->current_priority,
|
|
||||||
_Thread_Heir->current_priority
|
|
||||||
) == 1
|
|
||||||
) {
|
|
||||||
_Scheduler_Update_heir(
|
_Scheduler_Update_heir(
|
||||||
the_thread,
|
the_thread,
|
||||||
the_thread->current_priority == PRIORITY_PSEUDO_ISR
|
the_thread->current_priority == PRIORITY_PSEUDO_ISR
|
||||||
|
|||||||
@@ -26,16 +26,13 @@ void _Scheduler_EDF_Update_priority(
|
|||||||
Priority_Control new_priority
|
Priority_Control new_priority
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Scheduler_EDF_Node *node = _Scheduler_EDF_Thread_get_node( the_thread );
|
Scheduler_EDF_Node *node;
|
||||||
|
|
||||||
(void) scheduler;
|
node = _Scheduler_EDF_Thread_get_node( the_thread );
|
||||||
(void) new_priority;
|
|
||||||
|
|
||||||
if (node->queue_state == SCHEDULER_EDF_QUEUE_STATE_NEVER_HAS_BEEN) {
|
if ( ( new_priority & SCHEDULER_EDF_PRIO_MSB ) != 0 ) {
|
||||||
/* Shifts the priority to the region of background tasks. */
|
node->background_priority = new_priority;
|
||||||
the_thread->Start.initial_priority |= (SCHEDULER_EDF_PRIO_MSB);
|
|
||||||
the_thread->real_priority = the_thread->Start.initial_priority;
|
|
||||||
the_thread->current_priority = the_thread->Start.initial_priority;
|
|
||||||
node->queue_state = SCHEDULER_EDF_QUEUE_STATE_NOT_PRESENTLY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node->current_priority = new_priority;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,22 +26,14 @@ Scheduler_Void_or_thread _Scheduler_EDF_Yield(
|
|||||||
Thread_Control *the_thread
|
Thread_Control *the_thread
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Scheduler_EDF_Context *context =
|
Scheduler_EDF_Context *context;
|
||||||
_Scheduler_EDF_Get_context( scheduler );
|
Scheduler_EDF_Node *node;
|
||||||
Scheduler_EDF_Node *node = _Scheduler_EDF_Thread_get_node( the_thread );
|
|
||||||
|
|
||||||
/*
|
context = _Scheduler_EDF_Get_context( scheduler );
|
||||||
* The RBTree has more than one node, enqueue behind the tasks
|
node = _Scheduler_EDF_Thread_get_node( the_thread );
|
||||||
* with the same priority in case there are such ones.
|
|
||||||
*/
|
|
||||||
_RBTree_Extract( &context->Ready, &node->Node );
|
|
||||||
_RBTree_Insert(
|
|
||||||
&context->Ready,
|
|
||||||
&node->Node,
|
|
||||||
_Scheduler_EDF_Compare,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
|
_Scheduler_EDF_Extract( context, node );
|
||||||
|
_Scheduler_EDF_Enqueue( context, node, node->current_priority );
|
||||||
_Scheduler_EDF_Schedule_body( scheduler, the_thread, false );
|
_Scheduler_EDF_Schedule_body( scheduler, the_thread, false );
|
||||||
|
|
||||||
SCHEDULER_RETURN_VOID_OR_NULL;
|
SCHEDULER_RETURN_VOID_OR_NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user