From: Petr Benes Date: Fri, 13 May 2011 00:04:45 +0000 (+0200) Subject: edf: huge refactoring + late unblock protocol implementation X-Git-Url: http://rtime.felk.cvut.cz/gitweb/rtems-pluggable-edf.git/commitdiff_plain/c6ffcbd88a0c88d32bf613895caa7d6849ee3f8e edf: huge refactoring + late unblock protocol implementation The aim of this refactoring is separating the two scheduling layers. The low-level EDF uses RTEMS rate monotonic manager and server as its extension. The CBS atop of it is just responsible for inserting budget policies. The server implementation is still too tight to its thread because so far only one thread can be handled by a server at a time. Needs a fix-up. --- diff --git a/src/edf/scheduler_edf.c b/src/edf/scheduler_edf.c index 72cae70..03f6a32 100644 --- a/src/edf/scheduler_edf.c +++ b/src/edf/scheduler_edf.c @@ -10,48 +10,54 @@ #include -void edf_next_period(void) { - Thread_Control *the_thread = _Per_CPU_Information.executing; +inline void edf_postpone_deadlines(Thread_Control *the_thread) { RBT_Node *node = (RBT_Node*)the_thread->scheduler_info; - //FIXME: Think about this a bit more, what the order should be (making use of ratemonotonic) if (node->abs_deadline == 0) { // for the first time the_thread->real_priority = (_Watchdog_Ticks_since_boot + node->rel_deadline) % EDF_HYBRID_MASK; } else { // any other time the_thread->real_priority = (node->abs_deadline + node->rel_deadline) % EDF_HYBRID_MASK; } - node->abs_deadline = the_thread->current_priority = the_thread->real_priority; - if (node->cmp_time) - the_thread->cpu_time_budget = node->cmp_time; //FIXME: what units? - //_Scheduler_edf_Update(the_thread); - + node->abs_deadline = the_thread->current_priority = the_thread->real_priority; } // if cmp_time is 0, no CBS is used, only pure EDF -void edf_deadline_init(uint32_t __rel_deadline__, uint32_t __cmp_time__, rtems_asr_entry budget_overrun_handler) { - Thread_Control *the_thread = _Per_CPU_Information.executing; +rtems_status_code edf_next_period(rtems_id period_id, uint32_t __rel_deadline__, uint8_t flags) { + Thread_Control *the_thread = _Per_CPU_Information.executing; RBT_Node *node = (RBT_Node*)the_thread->scheduler_info; - node->rel_deadline = __rel_deadline__; - if (__cmp_time__) { - rtems_signal_catch(budget_overrun_handler, RTEMS_DEFAULT_MODES); - node->cmp_time = __cmp_time__; + + node->flags = flags; + + if (node->cmp_time) { +// rtems_signal_catch(budget_overrun_handler, RTEMS_DEFAULT_MODES); // register this in frsh the_thread->is_preemptible = true; - the_thread->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT; the_thread->budget_callout = (void *) edf_budget_overrun_callout; - rtems_timer_create(rtems_build_name( 'C', 'B', 'S', 'T' ), &node->timer_id); + the_thread->cpu_time_budget = node->cmp_time; + + // do not allow changing the rel_deadline when using a server + } else { + node->rel_deadline = __rel_deadline__; } + + edf_postpone_deadlines(the_thread); + + //_Scheduler_edf_Update(the_thread); + return rtems_rate_monotonic_period(period_id, __rel_deadline__); +} + + +rtems_status_code edf_deadline_init(rtems_name name, rtems_id *period_id) { + return rtems_rate_monotonic_create(name, period_id); } // return to start params -void edf_deadline_cancel(void) { +rtems_status_code edf_deadline_cancel(rtems_id period_id) { Thread_Control *the_thread = _Per_CPU_Information.executing; - RBT_Node *node = (RBT_Node*)the_thread->scheduler_info; + the_thread->real_priority = the_thread->Start.initial_priority + EDF_HYBRID_MASK; the_thread->current_priority = the_thread->real_priority; - if(node->cmp_time) - rtems_timer_delete(node->timer_id); - the_thread->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE; - the_thread->budget_callout = NULL; - _Scheduler_edf_Update(the_thread); + + _Scheduler_edf_Update(the_thread); + return rtems_rate_monotonic_delete(period_id); } // invoked when a limited time quantum (cmp_time) is exceeded @@ -165,6 +171,18 @@ void _Scheduler_edf_Update( Thread_Control *the_thread) { } void _Scheduler_edf_Unblock( Thread_Control *the_thread ) { + RBT_Node *node = (RBT_Node*)the_thread->scheduler_info; + + //Late unblock rule + if (node->flags & EDF_LATE_UNBLOCK) { + uint32_t Q_left = the_thread->cpu_time_budget; + uint32_t P_left = node->abs_deadline - _Watchdog_Ticks_since_boot; + uint32_t P = node->rel_deadline; + uint32_t Q = node->cmp_time; + if(P*Q_left > Q*P_left) + edf_postpone_deadlines(the_thread); + } + _Scheduler_edf_Enqueue(the_thread); /* TODO: flash critical section? */ diff --git a/src/edf/scheduler_edf.h b/src/edf/scheduler_edf.h index 3a4b55d..bd84554 100644 --- a/src/edf/scheduler_edf.h +++ b/src/edf/scheduler_edf.h @@ -12,14 +12,15 @@ EDF_Chain_Control _Thread_Ready_EDF_chain; /// This routine is called when a task starts to execute a new period or /// a first period. -void edf_next_period(void); +/// @param __rel_deadline__ in ticks, if a CBS is running, this option is ommited +/// @param flags Prepared for late unblock protocol +rtems_status_code edf_next_period(rtems_id period_id, uint32_t __rel_deadline__, uint8_t flags); /// Changes scheduling policy from priorities to deadlines -/// @param __rel_deadline__ in ticks required -void edf_deadline_init(uint32_t __rel_deadline__, uint32_t __cmp_time__, rtems_asr_entry budget_overrun_handler); +rtems_status_code edf_deadline_init(rtems_name name, rtems_id *period_id); /// Changes scheduling policy from deadlines to priorities -void edf_deadline_cancel(void); +rtems_status_code edf_deadline_cancel(rtems_id period_id); Thread_CPU_budget_algorithm_callout edf_budget_overrun_callout(); @@ -158,7 +159,7 @@ void _Scheduler_edf_Extract( * Deadline is later. * @return 1 for p1 > p2; 0 for p1 == p2; -1 for p1 < p2 */ -inline int _Scheduler_edf_Priority_compare ( +int _Scheduler_edf_Priority_compare ( Priority_Control p1, Priority_Control p2 );