]> rtime.felk.cvut.cz Git - rtems-pluggable-edf.git/blobdiff - src/edf/scheduler_edf.c
Budget and overrun handling moved from EDF part to CBS part
[rtems-pluggable-edf.git] / src / edf / scheduler_edf.c
index 8212a90621a0489e863f2c73bed2f2e0c8709994..e80cebffa92550baf2c52e2c5ffd9553f630d055 100644 (file)
 #include <stdint.h>
 
 
-/** 
- * The threads wanted to be served on a priority base will be assigned the very 
- * longest deadlines.
- */ 
-#define edf_initial_priority_shift(init_prio)  \
-       (init_prio + EDF_ABS_DEADLINE_MAX + 1)
-
-void edf_next_period(Thread_Control *the_thread) {
+inline void edf_postpone_deadlines(Thread_Control *the_thread) {
        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;
-       node->abs_deadline = the_thread->current_priority;      
+       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 cmp_time is 0, no CBS is used, only pure EDF
+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->flags = flags;
+       
+       // FIXME: remove cmp_time from EDF completely
+       if (node->cmp_time) {
+               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, node->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
+rtems_status_code edf_deadline_cancel(rtems_id period_id) {
+       Thread_Control *the_thread = _Per_CPU_Information.executing;
+       
+       the_thread->real_priority = the_thread->Start.initial_priority + EDF_HYBRID_MASK;
+       the_thread->current_priority = the_thread->real_priority;
+       
+       _Scheduler_edf_Update(the_thread);      
+       return rtems_rate_monotonic_delete(period_id);
 }
 
 
 
+//=======================================================================================
+
+
 int _Scheduler_edf_Priority_compare (Priority_Control p1, Priority_Control p2) {
        uint32_t time = _Watchdog_Ticks_since_boot;
        //correct priorities
@@ -44,6 +82,7 @@ void _Scheduler_edf_Initialize(void) {
        _Thread_Ready_EDF_chain.first = NULL;
        _Thread_Heir = NULL;
        _Thread_Executing = NULL;
+       _Signal_Manager_initialization();
 }
 
 void _Scheduler_edf_Block(  Thread_Control    *the_thread ) {
@@ -68,14 +107,18 @@ void * _Scheduler_edf_Allocate(  Thread_Control      *the_thread) {
        RBT_Node *schinfo;
        sched = _Workspace_Allocate (sizeof(RBT_Node));
        the_thread->scheduler_info = (RBT_Node *) sched;
-       the_thread->real_priority = the_thread->current_priority = edf_initial_priority_shift(the_thread->real_priority);
+       //edf_initial_priority_shift(&(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 = 2;
        schinfo->left = NULL;
        schinfo->right = NULL;
        schinfo->parent = NULL;
+       schinfo->cmp_time = 0;
        schinfo->ready_chain = &_Thread_Ready_EDF_chain;
        
        return sched;
@@ -86,21 +129,43 @@ 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;      
-       _Scheduler_edf_Extract(the_thread); 
-       _Scheduler_edf_Enqueue(the_thread); 
-       if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
-               _Thread_Heir = the_thread;
-               if ( _Thread_Executing->is_preemptible || the_thread->current_priority == 0 )
-                       _Thread_Dispatch_necessary = true;      
+       if(node->is_enqueued == 1) {
+               _Scheduler_edf_Extract(the_thread); 
+               _Scheduler_edf_Enqueue(the_thread); 
+               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;      
+               }
        }
 }
 
 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? */
 
@@ -121,6 +186,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 ) {
@@ -134,8 +200,8 @@ void _Scheduler_edf_Yield( void ) {
        ready      = sched_info->ready_chain;
        _ISR_Disable( level );
        if ( !_RBT_Has_only_one_node( ready ) ) {
-               _RBT_Extract(ready,executing); 
-               _RBT_Insert(ready,executing); // preserve the abs_deadline
+               _Scheduler_edf_Extract(executing); 
+               _Scheduler_edf_Enqueue(executing); // preserve the abs_deadline
 
                _ISR_Flash( level );
 
@@ -155,6 +221,7 @@ void _Scheduler_edf_Enqueue(  Thread_Control    *the_thread) {
        EDF_Chain_Control *chain = node->ready_chain;
 
        _RBT_Insert(chain,the_thread);
+       node->is_enqueued = 1;
 }
 
 void _Scheduler_edf_Enqueue_first(  Thread_Control    *the_thread) {
@@ -163,7 +230,10 @@ void _Scheduler_edf_Enqueue_first(  Thread_Control    *the_thread) {
 }
 
 void _Scheduler_edf_Extract(  Thread_Control     *the_thread) {
+       RBT_Node *node = (RBT_Node*)the_thread->scheduler_info;
        EDF_Chain_Control* chain = ((RBT_Node*)the_thread->scheduler_info)->ready_chain;
+       
        _RBT_Extract(chain,the_thread);
+       node->is_enqueued = 0;
 }