|
0
|
1 //========================================================================== |
|
|
2 // |
|
|
3 // sched/bitmap.cxx |
|
|
4 // |
|
|
5 // Bitmap scheduler class implementation |
|
|
6 // |
|
|
7 //========================================================================== |
|
|
8 //####COPYRIGHTBEGIN#### |
|
|
9 // |
|
|
10 // ------------------------------------------- |
|
|
11 // The contents of this file are subject to the Cygnus eCos Public License |
|
|
12 // Version 1.0 (the "License"); you may not use this file except in |
|
|
13 // compliance with the License. You may obtain a copy of the License at |
|
|
14 // http://sourceware.cygnus.com/ecos |
|
|
15 // |
|
|
16 // Software distributed under the License is distributed on an "AS IS" |
|
|
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
|
18 // License for the specific language governing rights and limitations under |
|
|
19 // the License. |
|
|
20 // |
|
|
21 // The Original Code is eCos - Embedded Cygnus Operating System, released |
|
|
22 // September 30, 1998. |
|
|
23 // |
|
|
24 // The Initial Developer of the Original Code is Cygnus. Portions created |
|
|
25 // by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved. |
|
|
26 // ------------------------------------------- |
|
|
27 // |
|
|
28 //####COPYRIGHTEND#### |
|
|
29 //========================================================================== |
|
|
30 //#####DESCRIPTIONBEGIN#### |
|
|
31 // |
|
|
32 // Author(s): nickg |
|
|
33 // Contributors: nickg |
|
|
34 // Date: 1997-09-16 |
|
|
35 // Purpose: Bitmap scheduler class implementation |
|
|
36 // Description: This file contains the implementations of |
|
|
37 // Cyg_Scheduler_Implementation and Cyg_SchedThread_Implementation. |
|
|
38 // |
|
|
39 // |
|
|
40 //####DESCRIPTIONEND#### |
|
|
41 // |
|
|
42 //========================================================================== |
|
|
43 |
|
|
44 #include <pkgconf/kernel.h> |
|
|
45 |
|
|
46 #include <cyg/kernel/ktypes.h> // base kernel types |
|
|
47 #include <cyg/infra/cyg_trac.h> // tracing macros |
|
|
48 #include <cyg/infra/cyg_ass.h> // assertion macros |
|
|
49 |
|
|
50 #include <cyg/kernel/sched.hxx> // our header |
|
|
51 |
|
|
52 #include <cyg/hal/hal_arch.h> // Architecture specific definitions |
|
|
53 |
|
|
54 #include <cyg/kernel/thread.inl> // thread inlines |
|
|
55 #include <cyg/kernel/sched.inl> // scheduler inlines |
|
|
56 |
|
|
57 #ifdef CYGSEM_KERNEL_SCHED_BITMAP |
|
|
58 |
|
|
59 //========================================================================== |
|
|
60 // Cyg_Scheduler_Implementation class members |
|
|
61 |
|
|
62 // ------------------------------------------------------------------------- |
|
|
63 // Constructor. |
|
|
64 |
|
|
65 Cyg_Scheduler_Implementation::Cyg_Scheduler_Implementation() |
|
|
66 { |
|
|
67 CYG_REPORT_FUNCTION(); |
|
|
68 |
|
|
69 // At present we cannot init run_queue here because the absence of |
|
|
70 // ordering of static constructors means that we could do this |
|
|
71 // after the static idle thread has been created. (Guess how I |
|
|
72 // found this out!) |
|
|
73 // run_queue = 0; |
|
|
74 |
|
|
75 } |
|
|
76 |
|
|
77 // ------------------------------------------------------------------------- |
|
|
78 // Choose the best thread to run next |
|
|
79 |
|
|
80 Cyg_Thread *Cyg_Scheduler_Implementation::schedule() |
|
|
81 { |
|
|
82 CYG_REPORT_FUNCTION(); |
|
|
83 |
|
|
84 // The run queue may _never_ be empty, there is always |
|
|
85 // an idle thread at the lowest priority. |
|
|
86 |
|
|
87 CYG_ASSERT(run_queue != 0, "Run queue empty"); |
|
|
88 |
|
|
89 cyg_uint32 index; |
|
|
90 |
|
|
91 HAL_LSBIT_INDEX(index, run_queue); |
|
|
92 |
|
|
93 return thread_table[index]; |
|
|
94 } |
|
|
95 |
|
|
96 // ------------------------------------------------------------------------- |
|
|
97 |
|
|
98 void Cyg_Scheduler_Implementation::add_thread(Cyg_Thread *thread) |
|
|
99 { |
|
|
100 CYG_REPORT_FUNCTION(); |
|
|
101 |
|
|
102 CYG_ASSERT( thread_table[thread->priority] == NULL || |
|
|
103 thread_table[thread->priority] == thread, |
|
|
104 "Duplicate thread priorities" ); |
|
|
105 |
|
|
106 CYG_ASSERT( (run_queue & (1<<thread->priority)) == 0, |
|
|
107 "Run queue bit already set" ); |
|
|
108 |
|
|
109 // If the thread is on some other queue, remove it |
|
|
110 // here. |
|
|
111 if( thread->queue != NULL ) |
|
|
112 { |
|
|
113 thread->queue->remove(thread); |
|
|
114 thread->queue = NULL; |
|
|
115 } |
|
|
116 |
|
|
117 run_queue |= 1<<thread->priority; |
|
|
118 |
|
|
119 // If the new thread is higher priority than the |
|
|
120 // current thread, request a reschedule. |
|
|
121 |
|
|
122 if( thread->priority < Cyg_Scheduler::get_current_thread()->priority ) |
|
|
123 need_reschedule = true; |
|
|
124 } |
|
|
125 |
|
|
126 // ------------------------------------------------------------------------- |
|
|
127 |
|
|
128 void Cyg_Scheduler_Implementation::rem_thread(Cyg_Thread *thread) |
|
|
129 { |
|
|
130 CYG_REPORT_FUNCTION(); |
|
|
131 |
|
|
132 CYG_ASSERT( thread_table[thread->priority] == thread, |
|
|
133 "Invalid thread priority" ); |
|
|
134 |
|
|
135 CYG_ASSERT( (run_queue & (1<<thread->priority)) != 0, |
|
|
136 "Run queue bit not set" ); |
|
|
137 |
|
|
138 run_queue &= ~(1<<thread->priority); |
|
|
139 |
|
|
140 if( thread == Cyg_Scheduler::get_current_thread() ) |
|
|
141 need_reschedule = true; |
|
|
142 } |
|
|
143 |
|
|
144 // ------------------------------------------------------------------------- |
|
|
145 // register thread with scheduler |
|
|
146 |
|
|
147 void Cyg_Scheduler_Implementation::register_thread(Cyg_Thread *thread) |
|
|
148 { |
|
|
149 CYG_REPORT_FUNCTION(); |
|
|
150 |
|
|
151 thread_table[thread->priority] = thread; |
|
|
152 } |
|
|
153 |
|
|
154 // ------------------------------------------------------------------------- |
|
|
155 |
|
|
156 // deregister thread |
|
|
157 void Cyg_Scheduler_Implementation::deregister_thread(Cyg_Thread *thread) |
|
|
158 { |
|
|
159 CYG_REPORT_FUNCTION(); |
|
|
160 |
|
|
161 thread_table[thread->priority] = NULL; |
|
|
162 } |
|
|
163 |
|
|
164 // ------------------------------------------------------------------------- |
|
|
165 // Test the given priority for uniqueness |
|
|
166 |
|
|
167 cyg_bool Cyg_Scheduler_Implementation::unique( cyg_priority priority) |
|
|
168 { |
|
|
169 CYG_REPORT_FUNCTION(); |
|
|
170 |
|
|
171 return thread_table[priority] == NULL; |
|
|
172 } |
|
|
173 |
|
|
174 |
|
|
175 //========================================================================== |
|
|
176 // Cyg_Cyg_SchedThread_Implementation class members |
|
|
177 |
|
|
178 Cyg_SchedThread_Implementation::Cyg_SchedThread_Implementation |
|
|
179 ( |
|
|
180 CYG_ADDRWORD sched_info |
|
|
181 ) |
|
|
182 { |
|
|
183 CYG_REPORT_FUNCTION(); |
|
|
184 |
|
|
185 #if 1 |
|
|
186 // Assign this thread's priority to the supplied sched_info |
|
|
187 // or the next highest priority available. |
|
|
188 |
|
|
189 priority = cyg_priority(sched_info); |
|
|
190 |
|
|
191 while( !Cyg_Scheduler::scheduler.unique(priority) ) |
|
|
192 priority++; |
|
|
193 |
|
|
194 #else |
|
|
195 // Assign initial priorities to threads in descending order of |
|
|
196 // creation. |
|
|
197 |
|
|
198 static cyg_priority init_priority = 0; |
|
|
199 |
|
|
200 priority = init_priority++; |
|
|
201 #endif |
|
|
202 |
|
|
203 } |
|
|
204 |
|
|
205 // ------------------------------------------------------------------------- |
|
|
206 |
|
|
207 void Cyg_SchedThread_Implementation::yield() |
|
|
208 { |
|
|
209 CYG_REPORT_FUNCTION(); |
|
|
210 |
|
|
211 // We cannot yield in this scheduler |
|
|
212 } |
|
|
213 |
|
|
214 //========================================================================== |
|
|
215 // Cyg_ThreadQueue_Implementation class members |
|
|
216 |
|
|
217 Cyg_ThreadQueue_Implementation::Cyg_ThreadQueue_Implementation() |
|
|
218 { |
|
|
219 CYG_REPORT_FUNCTION(); |
|
|
220 |
|
|
221 wait_queue = 0; // empty queue |
|
|
222 } |
|
|
223 |
|
|
224 |
|
|
225 void Cyg_ThreadQueue_Implementation::enqueue(Cyg_Thread *thread) |
|
|
226 { |
|
|
227 CYG_REPORT_FUNCTION(); |
|
|
228 |
|
|
229 wait_queue |= 1<<thread->priority; |
|
|
230 thread->queue = CYG_CLASSFROMBASE(Cyg_ThreadQueue, |
|
|
231 Cyg_ThreadQueue_Implementation, |
|
|
232 this); |
|
|
233 } |
|
|
234 |
|
|
235 // ------------------------------------------------------------------------- |
|
|
236 |
|
|
237 Cyg_Thread *Cyg_ThreadQueue_Implementation::dequeue() |
|
|
238 { |
|
|
239 CYG_REPORT_FUNCTION(); |
|
|
240 |
|
|
241 // Isolate ls bit in run_queue. |
|
|
242 cyg_sched_bitmap next_thread = wait_queue & -wait_queue; |
|
|
243 |
|
|
244 if( next_thread == 0 ) return NULL; |
|
|
245 |
|
|
246 wait_queue &= ~next_thread; |
|
|
247 |
|
|
248 cyg_uint32 index; |
|
|
249 |
|
|
250 HAL_LSBIT_INDEX(index, next_thread); |
|
|
251 |
|
|
252 Cyg_Thread *thread = Cyg_Scheduler::scheduler.thread_table[index]; |
|
|
253 |
|
|
254 thread->queue = NULL; |
|
|
255 |
|
|
256 return thread; |
|
|
257 } |
|
|
258 |
|
|
259 // ------------------------------------------------------------------------- |
|
|
260 |
|
|
261 Cyg_Thread *Cyg_ThreadQueue_Implementation::highpri() |
|
|
262 { |
|
|
263 CYG_REPORT_FUNCTION(); |
|
|
264 |
|
|
265 // Isolate ls bit in run_queue. |
|
|
266 cyg_sched_bitmap next_thread = wait_queue & -wait_queue; |
|
|
267 |
|
|
268 if( next_thread == 0 ) return NULL; |
|
|
269 |
|
|
270 cyg_uint32 index; |
|
|
271 |
|
|
272 HAL_LSBIT_INDEX(index, next_thread); |
|
|
273 |
|
|
274 return Cyg_Scheduler::scheduler.thread_table[index]; |
|
|
275 } |
|
|
276 |
|
|
277 // ------------------------------------------------------------------------- |
|
|
278 |
|
|
279 void Cyg_ThreadQueue_Implementation::remove(Cyg_Thread *thread) |
|
|
280 { |
|
|
281 CYG_REPORT_FUNCTION(); |
|
|
282 |
|
|
283 wait_queue &= ~(1<<thread->priority); |
|
|
284 thread->queue = NULL; |
|
|
285 } |
|
|
286 |
|
|
287 #endif |
|
|
288 |
|
|
289 // ------------------------------------------------------------------------- |
|
|
290 // EOF sched/bitmap.cxx |