#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
}
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? */
/// 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();
* 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
);