]> rtime.felk.cvut.cz Git - rtems-pluggable-edf.git/commitdiff
edf: huge refactoring + late unblock protocol implementation
authorPetr Benes <benesp16@fel.cvut.cz>
Fri, 13 May 2011 00:04:45 +0000 (02:04 +0200)
committerPetr Benes <benesp16@fel.cvut.cz>
Fri, 13 May 2011 00:04:45 +0000 (02:04 +0200)
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.

src/edf/scheduler_edf.c
src/edf/scheduler_edf.h

index 72cae70f4603ddbc9b47b6661494928d28af7f42..03f6a32f6a8736a6a72e0849b525c4545df986b7 100644 (file)
 #include <stdint.h>
 
 
-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? */
 
index 3a4b55d5aaa1184fa3903d0cc8682fb82a4c85dc..bd84554c8350113e80ef1338de935422ac5f7782 100644 (file)
@@ -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
 );