#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
_Thread_Ready_EDF_chain.first = NULL;
_Thread_Heir = NULL;
_Thread_Executing = NULL;
+ _Signal_Manager_initialization();
}
void _Scheduler_edf_Block( 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;
}
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? */
if ( _Thread_Executing->is_preemptible || the_thread->current_priority == 0 )
_Thread_Dispatch_necessary = true;
}
+
}
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 );
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) {
}
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;
}