]> rtime.felk.cvut.cz Git - rtems-pluggable-edf.git/blob - rtems-omk-template/appfoo/scheduler_edf.c
EDF project completely shuffled
[rtems-pluggable-edf.git] / rtems-omk-template / appfoo / scheduler_edf.c
1 #include "scheduler_edf.h"
2 #include "rbtree.h"
3 #include <stdio.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
10 /* let the scheduler talk */
11 //#define SCHED_VERBOSE
12
13
14 void _Scheduler_edf_Initialize(void) {
15         #ifdef SCHED_VERBOSE
16         printf("Sched: Initialize");
17         #endif
18         // initialize the RB tree
19         _Thread_Ready_EDF_chain.root = NULL;
20         _Thread_Ready_EDF_chain.first = NULL;
21         _Thread_Heir = NULL;
22         _Thread_Executing = NULL;
23 }
24
25 void _Scheduler_edf_Block(  Thread_Control    *the_thread ) {
26         #ifdef SCHED_VERBOSE
27         printf("Sched: Block");
28         #endif
29         _Scheduler_edf_Extract(the_thread);
30         
31         /* TODO: flash critical section? */
32
33         if ( _Thread_Is_heir( the_thread ) )
34                 _Scheduler_edf_Schedule();
35
36         if ( _Thread_Is_executing( the_thread ) )
37                 _Thread_Dispatch_necessary = true;      
38 }
39
40 void _Scheduler_edf_Schedule(void) {
41         #ifdef SCHED_VERBOSE
42         printf("Sched: Schedule");
43         #endif
44         // set the heir
45         _Thread_Heir = (Thread_Control *) _Thread_Ready_EDF_chain.first;
46 }
47
48 void * _Scheduler_edf_Allocate(  Thread_Control      *the_thread) {
49         #ifdef SCHED_VERBOSE
50         printf("Sched: Allocate");
51         #endif
52         void * sched;
53         RBT_Node *schinfo;
54         sched = _Workspace_Allocate (sizeof(RBT_Node));
55         the_thread->scheduler_info = (RBT_Node *) sched;
56         //the_thread->real_priority = ABS_DEADLINE_MAXIMUM - _Watchdog_Ticks_since_boot-2;
57         //the_thread->is_preemptible = TRUE;
58         //the_thread->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
59         //the_thread->budget_callout = NULL;
60         
61         schinfo = (RBT_Node *)(the_thread->scheduler_info);
62         schinfo->rel_deadline = the_thread->real_priority;
63         schinfo->abs_deadline = 0;
64         schinfo->left = NULL;
65         schinfo->right = NULL;
66         schinfo->parent = NULL;
67         schinfo->ready_chain = &_Thread_Ready_EDF_chain;
68         
69         return sched;
70 }
71
72 void _Scheduler_edf_Free(  Thread_Control      *the_thread) {
73         #ifdef SCHED_VERBOSE
74         printf("Sched: Free");
75         #endif
76         _Workspace_Free (the_thread->scheduler_info);
77 }
78
79 void _Scheduler_edf_Update(  Thread_Control      *the_thread) {
80         #ifdef SCHED_VERBOSE
81         printf("Sched: Update");
82         #endif
83         // after a priority changes, just extract and insert again
84         //in case it is in the tree
85 //      EDF_Chain_Control* chain = ((RBT_Node*)the_thread->scheduler_info)->ready_chain;
86 //      _RBT_Extract(chain, the_thread); 
87 //      _RBT_Insert(chain, the_thread); // preserve the abs_deadline
88 }
89
90 void _Scheduler_edf_Unblock(  Thread_Control    *the_thread ) {
91         #ifdef SCHED_VERBOSE
92         printf("Sched: Unblock");
93         #endif
94         _Scheduler_edf_Enqueue(the_thread);
95         /* TODO: flash critical section? */
96
97         /*
98         *  If the thread that was unblocked is more important than the heir,
99         *  then we have a new heir.  This may or may not result in a
100         *  context switch.
101         *
102         *  Normal case:
103         *    If the current thread is preemptible, then we need to do
104         *    a context switch.
105         *  Pseudo-ISR case:
106         *    Even if the thread isn't preemptible, if the new heir is
107         *    a pseudo-ISR system task, we need to do a context switch.
108         */
109         if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
110                 _Thread_Heir = the_thread;
111                 if ( _Thread_Executing->is_preemptible || the_thread->current_priority == 0 )
112                         _Thread_Dispatch_necessary = true;      
113         }
114 }
115
116 void _Scheduler_edf_Yield( void ) {
117         #ifdef SCHED_VERBOSE
118         printf("Sched: Yield");
119         #endif
120         
121         RBT_Node *sched_info;
122         ISR_Level                      level;
123         Thread_Control                *executing;
124         EDF_Chain_Control                 *ready;
125
126         executing  = _Thread_Executing;
127         sched_info = (RBT_Node *) executing->scheduler_info;
128         ready      = sched_info->ready_chain;
129         _ISR_Disable( level );
130         if ( !_RBT_Has_only_one_node( ready ) ) {
131                 _RBT_Extract(ready,executing); 
132                 _RBT_Insert(ready,executing); // preserve the abs_deadline
133
134                 _ISR_Flash( level );
135
136                 if ( _Thread_Is_heir( executing ) )
137                         _Thread_Heir = (Thread_Control *) ready->first;
138                 _Thread_Dispatch_necessary = TRUE;
139         }
140         else if ( !_Thread_Is_heir( executing ) )
141                 _Thread_Dispatch_necessary = TRUE;
142
143         _ISR_Enable( level );
144         
145 }
146
147 void _Scheduler_edf_Enqueue(  Thread_Control    *the_thread) {
148         #ifdef SCHED_VERBOSE
149         printf("Sched: Enqueue");
150         #endif
151         RBT_Node *node = (RBT_Node*)the_thread->scheduler_info;
152         EDF_Chain_Control *chain = node->ready_chain;
153         if (node->rel_deadline == 255) //hack for idle task
154                 node->abs_deadline = ABS_DEADLINE_MAXIMUM;      
155         else
156                 node->abs_deadline = _Watchdog_Ticks_since_boot + node->rel_deadline;
157         _RBT_Insert(chain,the_thread);
158
159 }
160
161 void _Scheduler_edf_Enqueue_first(  Thread_Control    *the_thread) {
162         #ifdef SCHED_VERBOSE
163         printf("Sched: Enqueue_first");
164         #endif
165         // FIXME: force first position
166         _Scheduler_edf_Enqueue(the_thread);
167 }
168
169 void _Scheduler_edf_Extract(  Thread_Control     *the_thread) {
170         #ifdef SCHED_VERBOSE
171         printf("Sched: Extract");
172         #endif
173         EDF_Chain_Control* chain = ((RBT_Node*)the_thread->scheduler_info)->ready_chain;
174         _RBT_Extract(chain,the_thread);
175 }
176