From 99fc1d1d1b44e70a0bed4c94a514bd3f3b5df64f Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 9 Jun 2016 21:30:40 +0200 Subject: 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. --- cpukit/score/src/schedulercbsunblock.c | 56 ++++++++++++++++------------------ 1 file changed, 26 insertions(+), 30 deletions(-) (limited to 'cpukit/score/src/schedulercbsunblock.c') diff --git a/cpukit/score/src/schedulercbsunblock.c b/cpukit/score/src/schedulercbsunblock.c index 05e155a4c3..3f5bd33623 100644 --- a/cpukit/score/src/schedulercbsunblock.c +++ b/cpukit/score/src/schedulercbsunblock.c @@ -30,12 +30,15 @@ Scheduler_Void_or_thread _Scheduler_CBS_Unblock( Thread_Control *the_thread ) { - Scheduler_CBS_Node *node = _Scheduler_CBS_Thread_get_node( the_thread ); - Scheduler_CBS_Server *serv_info = node->cbs_server; - Priority_Control new_priority; + Scheduler_EDF_Context *context; + Scheduler_CBS_Node *node; + Scheduler_CBS_Server *serv_info; + Priority_Control priority; - _Scheduler_EDF_Enqueue( scheduler, the_thread ); - /* TODO: flash critical section? */ + context = _Scheduler_EDF_Get_context( scheduler ); + 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 @@ -43,29 +46,30 @@ Scheduler_Void_or_thread _Scheduler_CBS_Unblock( * without increased utilization of this task. It might cause a deadline * 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 budget = serv_info->parameters.budget; - time_t deadline_left = the_thread->cpu_time_budget; - time_t budget_left = the_thread->real_priority - - _Watchdog_Ticks_since_boot; + uint32_t deadline_left = the_thread->cpu_time_budget; + Priority_Control budget_left = priority - _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. */ - new_priority = the_thread->Start.initial_priority; - the_thread->real_priority = new_priority; - if ( the_thread->current_priority != new_priority ) { - the_thread->current_priority = new_priority; - _Scheduler_EDF_Change_priority( - scheduler, - the_thread, - new_priority, - true - ); + + priority = node->Base.background_priority; + the_thread->real_priority = priority; + + if ( + _Thread_Priority_less_than( the_thread->current_priority, priority ) + || !_Thread_Owns_resources( the_thread ) + ) { + 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, * 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 * a pseudo-ISR system task, we need to do a context switch. */ - if ( - _Scheduler_EDF_Priority_compare( - the_thread->current_priority, - _Thread_Heir->current_priority - ) == 1 - ) { - _Scheduler_Update_heir( - the_thread, - the_thread->current_priority == PRIORITY_PSEUDO_ISR - ); + if ( priority < _Thread_Heir->current_priority ) { + _Scheduler_Update_heir( the_thread, priority == PRIORITY_PSEUDO_ISR ); } SCHEDULER_RETURN_VOID_OR_NULL; -- cgit v1.2.3