]> rtime.felk.cvut.cz Git - rtems-pluggable-edf.git/commitdiff
Scheduler modified in order to have an extention of CBS.
authorPetr Benes <benesp16@fel.cvut.cz>
Sun, 17 Apr 2011 13:20:02 +0000 (15:20 +0200)
committerPetr Benes <benesp16@fel.cvut.cz>
Sun, 17 Apr 2011 13:20:02 +0000 (15:20 +0200)
The CBS does not work yet.

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

index b9c461fe978f9a74ac76a95f21f2ad4d74f4ffbb..9ac043b65bc7e4b9959f24a28975d59e68d8db77 100644 (file)
@@ -7,6 +7,8 @@ extern "C" {
 
 #include "edf_types.h"
 #include <stdint.h>
+
+#include <rtems/shell.h>
        
 // This struct will be embedded into the Thread_Control control 
 // as scheduler_info 
@@ -19,6 +21,8 @@ typedef struct RBT_node_struct {
        Node_Color       color;
        EDF_Chain_Control *ready_chain;
        uint8_t is_enqueued;
+       uint32_t cmp_time; 
+       rtems_id timer_id;
 } RBT_Node;
 
 void _RBT_Insert(EDF_Chain_Control *chain,EDF_Node *node);
index 51f76529eb6b5177e72cf0f5eedac2a5755a2a93..536fa2acf82e3a524007d5a9be439dbcc5ab150d 100644 (file)
 void edf_next_period(void) {
        Thread_Control *the_thread = _Per_CPU_Information.executing;    
        RBT_Node *node = (RBT_Node*)the_thread->scheduler_info; 
-       the_thread->real_priority = the_thread->current_priority = (_Watchdog_Ticks_since_boot + node->rel_deadline) % EDF_HYBRID_MASK;
-       _Scheduler_edf_Update(the_thread);
+       //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);
+
 }
 
-void edf_deadline_init(uint32_t __rel_deadline__) {
+// 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;
        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__;
+               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);
+       }
 }
 
+// return to start params
 void edf_deadline_cancel(void) {
        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);
 }
 
+// invoked when a limited time quantum (cmp_time) is exceeded
+Thread_CPU_budget_algorithm_callout edf_budget_overrun_callout() {
+       Thread_Control *the_thread = _Per_CPU_Information.executing;    
+       RBT_Node *node = (RBT_Node*)the_thread->scheduler_info; 
+       rtems_signal_send(the_thread->Object.id, RTEMS_SIGNAL_18);
+       _Thread_Suspend (the_thread);
+       //wait until next period to enable the task again
+       uint32_t ticks = node->abs_deadline - _Watchdog_Ticks_since_boot;
+       rtems_timer_fire_after(node->timer_id, ticks, (void *) edf_budget_overrun_reenable, the_thread);
+       return 0;
+}
+
+rtems_timer_service_routine_entry edf_budget_overrun_reenable(Thread_Control *the_thread) {
+       _Thread_Resume(the_thread, false);
+       return 0;
+}
+
 //=======================================================================================
 
+
 int _Scheduler_edf_Priority_compare (Priority_Control p1, Priority_Control p2) {
        uint32_t time = _Watchdog_Ticks_since_boot;
        //correct priorities
@@ -77,16 +119,16 @@ void * _Scheduler_edf_Allocate(  Thread_Control      *the_thread) {
        the_thread->scheduler_info = (RBT_Node *) sched;
        //edf_initial_priority_shift(&(the_thread->real_priority));
        
-       the_thread->real_priority += (EDF_HYBRID_MASK);
-       the_thread->current_priority = the_thread->real_priority;
+       the_thread->Start.initial_priority += (EDF_HYBRID_MASK);
        
        schinfo = (RBT_Node *)(the_thread->scheduler_info);
        schinfo->rel_deadline = 0;      // This has to be negotiated afterwards
        schinfo->abs_deadline = 0;
-       schinfo->is_enqueued = 0;
+       schinfo->is_enqueued = 2;
        schinfo->left = NULL;
        schinfo->right = NULL;
        schinfo->parent = NULL;
+       schinfo->cmp_time = 0;
        schinfo->ready_chain = &_Thread_Ready_EDF_chain;
        
        return sched;
@@ -98,15 +140,22 @@ void _Scheduler_edf_Free(  Thread_Control      *the_thread) {
 
 void _Scheduler_edf_Update(  Thread_Control      *the_thread) {
        RBT_Node *node = (RBT_Node*)the_thread->scheduler_info;
+       // Make sure the previous priority meaning does not show up
+       // if the task was just initialized
+       if (node->is_enqueued == 2) {
+               the_thread->real_priority = the_thread->Start.initial_priority;
+               the_thread->current_priority = the_thread->real_priority;               
+               node->is_enqueued = 0;
+       }
        // Update deadlines for deadline driven tasks
-       if (!(the_thread->current_priority && EDF_HYBRID_MASK))
+       if (!(the_thread->current_priority & EDF_HYBRID_MASK))
                ((RBT_Node*)the_thread->scheduler_info)->abs_deadline = the_thread->current_priority;   
        else
                ((RBT_Node*)the_thread->scheduler_info)->abs_deadline = 0;      
-       if(node->is_enqueued) {
+       if(node->is_enqueued == 1) {
                _Scheduler_edf_Extract(the_thread); 
                _Scheduler_edf_Enqueue(the_thread); 
-               if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
+               if ( the_thread->current_priority < _Thread_Heir->current_priority ) { //TODO: compare priorities
                        _Thread_Heir = the_thread;
                        if ( _Thread_Executing->is_preemptible || the_thread->current_priority == 0 )
                                _Thread_Dispatch_necessary = true;      
@@ -135,6 +184,7 @@ void _Scheduler_edf_Unblock(  Thread_Control    *the_thread ) {
                if ( _Thread_Executing->is_preemptible || the_thread->current_priority == 0 )
                        _Thread_Dispatch_necessary = true;      
        }
+
 }
 
 void _Scheduler_edf_Yield( void ) {
index a53cc34fe5776de5334cf8d9c47b516212d0d1c6..ed4ba3519530c189705cb55ff8ab4672ab086fb4 100644 (file)
@@ -16,12 +16,14 @@ void edf_next_period(void);
 
 /// Changes scheduling policy from priorities to deadlines
 /// @param __rel_deadline__ in ticks required
-void edf_deadline_init(uint32_t __rel_deadline__);
+void edf_deadline_init(uint32_t __rel_deadline__, uint32_t __cmp_time__, rtems_asr_entry *budget_overrun_handler);
 
 /// Changes scheduling policy from deadlines to priorities
 void edf_deadline_cancel(void);
 
+Thread_CPU_budget_algorithm_callout edf_budget_overrun_callout();
 
+rtems_timer_service_routine_entry edf_budget_overrun_reenable(Thread_Control *the_thread);
 
 
 /// Pluggable scheduler callback functions