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.
-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;
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;
}
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
}
// 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;
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->is_preemptible = true;
- the_thread->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT;
the_thread->budget_callout = (void *) edf_budget_overrun_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
}
// 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;
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;
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
}
// invoked when a limited time quantum (cmp_time) is exceeded
}
void _Scheduler_edf_Unblock( 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? */
_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.
/// 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
/// 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
/// 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();
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
*/
* 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
);
Priority_Control p1,
Priority_Control p2
);