1 #include "scheduler_edf.h"
4 #include <rtems/system.h>
5 #include <rtems/score/isr.h>
6 #include <rtems/score/watchdog.h>
7 #include <rtems/score/wkspace.h>
8 #include <rtems/score/percpu.h>
9 #include <rtems/score/thread.h>
14 * The threads wanted to be served on a priority base will be assigned the very
17 #define edf_initial_priority_shift(init_prio) \
18 (init_prio + EDF_ABS_DEADLINE_MAX + 1)
20 void edf_next_period(Thread_Control *the_thread) {
21 RBT_Node *node = (RBT_Node*)the_thread->scheduler_info;
22 the_thread->real_priority = the_thread->current_priority = (_Watchdog_Ticks_since_boot + node->rel_deadline) % EDF_HYBRID_MASK;
23 node->abs_deadline = the_thread->current_priority;
28 int _Scheduler_edf_Priority_compare (Priority_Control p1, Priority_Control p2) {
29 uint32_t time = _Watchdog_Ticks_since_boot;
31 if (p1 < EDF_HYBRID_MASK)
32 p1 = (p1 - time) % EDF_HYBRID_MASK;
33 if (p2 < EDF_HYBRID_MASK)
34 p2 = (p2 - time) % EDF_HYBRID_MASK;
35 if (p1 > p2) return -1;
36 else if (p1 < p2) return 1;
41 void _Scheduler_edf_Initialize(void) {
42 // initialize the RB tree
43 _Thread_Ready_EDF_chain.root = NULL;
44 _Thread_Ready_EDF_chain.first = NULL;
46 _Thread_Executing = NULL;
49 void _Scheduler_edf_Block( Thread_Control *the_thread ) {
50 _Scheduler_edf_Extract(the_thread);
52 /* TODO: flash critical section? */
54 if ( _Thread_Is_heir( the_thread ) )
55 _Scheduler_edf_Schedule();
57 if ( _Thread_Is_executing( the_thread ) )
58 _Thread_Dispatch_necessary = true;
61 void _Scheduler_edf_Schedule(void) {
63 _Thread_Heir = (Thread_Control *) _Thread_Ready_EDF_chain.first;
66 void * _Scheduler_edf_Allocate( Thread_Control *the_thread) {
69 sched = _Workspace_Allocate (sizeof(RBT_Node));
70 the_thread->scheduler_info = (RBT_Node *) sched;
71 the_thread->real_priority = the_thread->current_priority = edf_initial_priority_shift(the_thread->real_priority);
73 schinfo = (RBT_Node *)(the_thread->scheduler_info);
74 schinfo->rel_deadline = 0; // This has to be negotiated afterwards
75 schinfo->abs_deadline = 0;
77 schinfo->right = NULL;
78 schinfo->parent = NULL;
79 schinfo->ready_chain = &_Thread_Ready_EDF_chain;
84 void _Scheduler_edf_Free( Thread_Control *the_thread) {
85 _Workspace_Free (the_thread->scheduler_info);
88 void _Scheduler_edf_Update( Thread_Control *the_thread) {
89 // Update deadlines for deadline driven tasks
90 if (!(the_thread->current_priority && EDF_HYBRID_MASK))
91 ((RBT_Node*)the_thread->scheduler_info)->abs_deadline = the_thread->current_priority;
93 ((RBT_Node*)the_thread->scheduler_info)->abs_deadline = 0;
94 _Scheduler_edf_Extract(the_thread);
95 _Scheduler_edf_Enqueue(the_thread);
96 if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
97 _Thread_Heir = the_thread;
98 if ( _Thread_Executing->is_preemptible || the_thread->current_priority == 0 )
99 _Thread_Dispatch_necessary = true;
103 void _Scheduler_edf_Unblock( Thread_Control *the_thread ) {
104 _Scheduler_edf_Enqueue(the_thread);
105 /* TODO: flash critical section? */
108 * If the thread that was unblocked is more important than the heir,
109 * then we have a new heir. This may or may not result in a
113 * If the current thread is preemptible, then we need to do
116 * Even if the thread isn't preemptible, if the new heir is
117 * a pseudo-ISR system task, we need to do a context switch.
119 if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
120 _Thread_Heir = the_thread;
121 if ( _Thread_Executing->is_preemptible || the_thread->current_priority == 0 )
122 _Thread_Dispatch_necessary = true;
126 void _Scheduler_edf_Yield( void ) {
127 RBT_Node *sched_info;
129 Thread_Control *executing;
130 EDF_Chain_Control *ready;
132 executing = _Thread_Executing;
133 sched_info = (RBT_Node *) executing->scheduler_info;
134 ready = sched_info->ready_chain;
135 _ISR_Disable( level );
136 if ( !_RBT_Has_only_one_node( ready ) ) {
137 _RBT_Extract(ready,executing);
138 _RBT_Insert(ready,executing); // preserve the abs_deadline
142 if ( _Thread_Is_heir( executing ) )
143 _Thread_Heir = (Thread_Control *) ready->first;
144 _Thread_Dispatch_necessary = TRUE;
146 else if ( !_Thread_Is_heir( executing ) )
147 _Thread_Dispatch_necessary = TRUE;
149 _ISR_Enable( level );
153 void _Scheduler_edf_Enqueue( Thread_Control *the_thread) {
154 RBT_Node *node = (RBT_Node*)the_thread->scheduler_info;
155 EDF_Chain_Control *chain = node->ready_chain;
157 _RBT_Insert(chain,the_thread);
160 void _Scheduler_edf_Enqueue_first( Thread_Control *the_thread) {
161 // FIXME: force first position
162 _Scheduler_edf_Enqueue(the_thread);
165 void _Scheduler_edf_Extract( Thread_Control *the_thread) {
166 EDF_Chain_Control* chain = ((RBT_Node*)the_thread->scheduler_info)->ready_chain;
167 _RBT_Extract(chain,the_thread);