|
0
|
1 //========================================================================== |
|
|
2 // |
|
2
|
3 // sched/mlqueue.cxx |
|
0
|
4 // |
|
2
|
5 // Multi-level queue scheduler class implementation |
|
0
|
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 |
|
2
|
25 // by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. |
|
0
|
26 // ------------------------------------------- |
|
|
27 // |
|
|
28 //####COPYRIGHTEND#### |
|
|
29 //========================================================================== |
|
|
30 //#####DESCRIPTIONBEGIN#### |
|
|
31 // |
|
2
|
32 // Author(s): nickg |
|
|
33 // Contributors: nickg, jlarmour |
|
|
34 // Date: 1999-02-17 |
|
|
35 // Purpose: Multilevel queue scheduler class implementation |
|
|
36 // Description: This file contains the implementations of |
|
|
37 // Cyg_Scheduler_Implementation and |
|
|
38 // Cyg_SchedThread_Implementation. |
|
0
|
39 // |
|
|
40 // |
|
|
41 //####DESCRIPTIONEND#### |
|
|
42 // |
|
|
43 //========================================================================== |
|
|
44 |
|
|
45 #include <pkgconf/kernel.h> |
|
|
46 |
|
|
47 #include <cyg/kernel/ktypes.h> // base kernel types |
|
|
48 #include <cyg/infra/cyg_trac.h> // tracing macros |
|
|
49 #include <cyg/infra/cyg_ass.h> // assertion macros |
|
|
50 |
|
|
51 #include <cyg/kernel/sched.hxx> // our header |
|
|
52 |
|
|
53 #include <cyg/hal/hal_arch.h> // Architecture specific definitions |
|
|
54 |
|
|
55 #include <cyg/kernel/thread.inl> // thread inlines |
|
|
56 #include <cyg/kernel/sched.inl> // scheduler inlines |
|
|
57 |
|
|
58 #ifdef CYGSEM_KERNEL_SCHED_MLQUEUE |
|
|
59 |
|
|
60 //------------------------------------------------------------------------- |
|
|
61 // Some local tracing control - a default. |
|
|
62 #ifdef CYGDBG_USE_TRACING |
|
|
63 # if !defined( CYGDBG_INFRA_DEBUG_TRACE_ASSERT_SIMPLE ) && \ |
|
|
64 !defined( CYGDBG_INFRA_DEBUG_TRACE_ASSERT_FANCY ) |
|
|
65 // ie. not a tracing implementation that takes a long time to output |
|
|
66 |
|
|
67 # ifndef CYGDBG_KERNEL_TRACE_TIMESLICE |
|
|
68 # define CYGDBG_KERNEL_TRACE_TIMESLICE |
|
|
69 # endif // control not already defined |
|
|
70 |
|
|
71 # endif // trace implementation not ..._SIMPLE && not ..._FANCY |
|
|
72 #endif // CYGDBG_USE_TRACING |
|
|
73 |
|
|
74 //========================================================================== |
|
|
75 // Cyg_Scheduler_Implementation class static members |
|
|
76 |
|
|
77 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE |
|
|
78 |
|
|
79 cyg_ucount32 Cyg_Scheduler_Implementation::timeslice_count = |
|
|
80 CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS; |
|
|
81 |
|
|
82 #endif |
|
|
83 |
|
|
84 |
|
|
85 //========================================================================== |
|
|
86 // Cyg_Scheduler_Implementation class members |
|
|
87 |
|
|
88 // ------------------------------------------------------------------------- |
|
|
89 // Constructor. |
|
|
90 |
|
|
91 Cyg_Scheduler_Implementation::Cyg_Scheduler_Implementation() |
|
|
92 { |
|
|
93 CYG_REPORT_FUNCTION(); |
|
|
94 |
|
|
95 queue_map = 0; |
|
2
|
96 |
|
|
97 CYG_REPORT_RETURN(); |
|
0
|
98 } |
|
|
99 |
|
|
100 // ------------------------------------------------------------------------- |
|
|
101 // Choose the best thread to run next |
|
|
102 |
|
2
|
103 Cyg_Thread * |
|
|
104 Cyg_Scheduler_Implementation::schedule(void) |
|
0
|
105 { |
|
2
|
106 CYG_REPORT_FUNCTYPE("returning thread %08x"); |
|
0
|
107 |
|
|
108 // The run queue may _never_ be empty, there is always |
|
|
109 // an idle thread at the lowest priority. |
|
|
110 |
|
|
111 CYG_ASSERT( queue_map != 0, "Run queue empty"); |
|
|
112 CYG_ASSERT( queue_map & (1<<CYG_THREAD_MIN_PRIORITY), "Idle thread vanished!!!"); |
|
|
113 CYG_ASSERT( !run_queue[CYG_THREAD_MIN_PRIORITY].empty(), "Idle thread vanished!!!"); |
|
|
114 |
|
|
115 register cyg_uint32 index; |
|
|
116 |
|
|
117 HAL_LSBIT_INDEX(index, queue_map); |
|
|
118 |
|
|
119 Cyg_Thread *thread = run_queue[index].highpri(); |
|
|
120 |
|
|
121 CYG_ASSERT( thread != NULL , "No threads in run queue"); |
|
|
122 |
|
2
|
123 CYG_REPORT_RETVAL(thread); |
|
|
124 |
|
0
|
125 return thread; |
|
|
126 } |
|
|
127 |
|
|
128 // ------------------------------------------------------------------------- |
|
|
129 |
|
2
|
130 void |
|
|
131 Cyg_Scheduler_Implementation::add_thread(Cyg_Thread *thread) |
|
0
|
132 { |
|
|
133 CYG_REPORT_FUNCTION(); |
|
2
|
134 CYG_REPORT_FUNCARG1("thread=%08x", thread); |
|
0
|
135 |
|
|
136 cyg_priority pri = thread->priority; |
|
|
137 Cyg_ThreadQueue_Implementation *queue = &run_queue[pri]; |
|
|
138 |
|
|
139 // If the thread is on some other queue, remove it |
|
|
140 // here. |
|
|
141 if( thread->queue != NULL ) |
|
|
142 { |
|
|
143 thread->queue->remove(thread); |
|
|
144 thread->queue = NULL; |
|
|
145 } |
|
|
146 |
|
|
147 if( queue->empty() ) |
|
|
148 { |
|
|
149 // set the map bit and ask for a reschedule if this is a |
|
|
150 // new highest priority thread. |
|
|
151 |
|
|
152 queue_map |= (1<<pri); |
|
|
153 |
|
|
154 // If the new thread is higher priority than the |
|
|
155 // current thread, request a reschedule. |
|
|
156 |
|
|
157 if( pri < Cyg_Scheduler::get_current_thread()->priority ) |
|
|
158 need_reschedule = true; |
|
|
159 |
|
|
160 } |
|
|
161 // else the queue already has an occupant, queue behind him |
|
|
162 |
|
|
163 CYG_ASSERT( queue_map != 0, "Run queue empty"); |
|
|
164 CYG_ASSERT( queue_map & (1<<pri), "Queue map bit not set for pri"); |
|
|
165 CYG_ASSERT( queue_map & (1<<CYG_THREAD_MIN_PRIORITY), "Idle thread vanished!!!"); |
|
|
166 // CYG_ASSERT( !run_queue[CYG_THREAD_MIN_PRIORITY].empty(), "Idle thread vanished!!!"); |
|
|
167 |
|
2
|
168 queue->enqueue(thread); |
|
|
169 |
|
|
170 CYG_REPORT_RETURN(); |
|
0
|
171 } |
|
|
172 |
|
|
173 // ------------------------------------------------------------------------- |
|
|
174 |
|
2
|
175 void |
|
|
176 Cyg_Scheduler_Implementation::rem_thread(Cyg_Thread *thread) |
|
0
|
177 { |
|
|
178 CYG_REPORT_FUNCTION(); |
|
2
|
179 CYG_REPORT_FUNCARG1("thread=%08x", thread); |
|
0
|
180 |
|
|
181 CYG_ASSERT( queue_map != 0, "Run queue empty"); |
|
|
182 |
|
|
183 cyg_priority pri = thread->priority; |
|
|
184 Cyg_ThreadQueue_Implementation *queue = &run_queue[pri]; |
|
|
185 |
|
|
186 CYG_ASSERT( pri != CYG_THREAD_MIN_PRIORITY, "Idle thread trying to sleep!"); |
|
|
187 CYG_ASSERT( queue_map & (1<<pri), "Queue map bit not set for pri"); |
|
|
188 CYG_ASSERT( !run_queue[CYG_THREAD_MIN_PRIORITY].empty(), "Idle thread vanished!!!"); |
|
|
189 |
|
|
190 // remove thread from queue |
|
|
191 queue->remove(thread); |
|
|
192 |
|
|
193 if( queue->empty() ) |
|
|
194 { |
|
|
195 // If this was only thread in |
|
|
196 // queue, clear map. |
|
|
197 |
|
|
198 queue_map &= ~(1<<pri); |
|
|
199 } |
|
|
200 |
|
|
201 CYG_ASSERT( queue_map != 0, "Run queue empty"); |
|
|
202 CYG_ASSERT( queue_map & (1<<CYG_THREAD_MIN_PRIORITY), "Idle thread vanished!!!"); |
|
|
203 CYG_ASSERT( !run_queue[CYG_THREAD_MIN_PRIORITY].empty(), "Idle thread vanished!!!"); |
|
2
|
204 |
|
|
205 CYG_REPORT_RETURN(); |
|
0
|
206 } |
|
|
207 |
|
|
208 // ------------------------------------------------------------------------- |
|
|
209 // register thread with scheduler |
|
|
210 |
|
2
|
211 void |
|
|
212 Cyg_Scheduler_Implementation::register_thread(Cyg_Thread *thread) |
|
0
|
213 { |
|
|
214 CYG_REPORT_FUNCTION(); |
|
2
|
215 CYG_REPORT_FUNCARG1("thread=%08x", thread); |
|
0
|
216 // No registration necessary in this scheduler |
|
2
|
217 CYG_REPORT_RETURN(); |
|
0
|
218 } |
|
|
219 |
|
|
220 // ------------------------------------------------------------------------- |
|
|
221 |
|
|
222 // deregister thread |
|
2
|
223 void |
|
|
224 Cyg_Scheduler_Implementation::deregister_thread(Cyg_Thread *thread) |
|
0
|
225 { |
|
|
226 CYG_REPORT_FUNCTION(); |
|
2
|
227 CYG_REPORT_FUNCARG1("thread=%08x", thread); |
|
0
|
228 // No registration necessary in this scheduler |
|
2
|
229 CYG_REPORT_RETURN(); |
|
0
|
230 } |
|
|
231 |
|
|
232 // ------------------------------------------------------------------------- |
|
|
233 // Test the given priority for uniqueness |
|
|
234 |
|
2
|
235 cyg_bool |
|
|
236 Cyg_Scheduler_Implementation::unique( cyg_priority priority) |
|
0
|
237 { |
|
2
|
238 CYG_REPORT_FUNCTYPE("returning %d"); |
|
|
239 CYG_REPORT_FUNCARG1("priority=%d", priority); |
|
0
|
240 // Priorities are not unique |
|
2
|
241 CYG_REPORT_RETVAL(true); |
|
0
|
242 return true; |
|
|
243 } |
|
|
244 |
|
|
245 //========================================================================== |
|
|
246 // Support for timeslicing option |
|
|
247 |
|
|
248 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE |
|
|
249 |
|
2
|
250 void |
|
|
251 Cyg_Scheduler_Implementation::timeslice(void) |
|
0
|
252 { |
|
|
253 #ifdef CYGDBG_KERNEL_TRACE_TIMESLICE |
|
|
254 CYG_REPORT_FUNCTION(); |
|
|
255 #endif |
|
|
256 CYG_ASSERT( queue_map != 0, "Run queue empty"); |
|
|
257 CYG_ASSERT( queue_map & (1<<CYG_THREAD_MIN_PRIORITY), "Idle thread vanished!!!"); |
|
|
258 |
|
|
259 if( --timeslice_count == 0 ) |
|
|
260 { |
|
|
261 CYG_INSTRUMENT_SCHED(TIMESLICE,0,0); |
|
|
262 #ifdef CYGDBG_KERNEL_TRACE_TIMESLICE |
|
|
263 CYG_TRACE0( true, "quantum consumed, time to reschedule" ); |
|
|
264 #endif |
|
|
265 // And force the current thread to yield. |
|
|
266 current_thread->yield(); |
|
|
267 } |
|
|
268 |
|
|
269 CYG_ASSERT( queue_map & (1<<CYG_THREAD_MIN_PRIORITY), "Idle thread vanished!!!"); |
|
|
270 CYG_ASSERT( !run_queue[CYG_THREAD_MIN_PRIORITY].empty(), "Idle thread vanished!!!"); |
|
|
271 #ifdef CYGDBG_KERNEL_TRACE_TIMESLICE |
|
|
272 CYG_REPORT_RETURN(); |
|
|
273 #endif |
|
|
274 } |
|
|
275 |
|
|
276 #endif |
|
|
277 |
|
|
278 //========================================================================== |
|
|
279 // Cyg_Cyg_SchedThread_Implementation class members |
|
|
280 |
|
|
281 Cyg_SchedThread_Implementation::Cyg_SchedThread_Implementation |
|
|
282 ( |
|
|
283 CYG_ADDRWORD sched_info |
|
|
284 ) |
|
|
285 { |
|
|
286 CYG_REPORT_FUNCTION(); |
|
2
|
287 CYG_REPORT_FUNCARG1("sched_info=%08x", sched_info); |
|
0
|
288 |
|
|
289 // Create all threads at maximum priority |
|
|
290 priority = (cyg_priority)sched_info; |
|
|
291 |
|
|
292 // point the next and prev field at this thread. |
|
|
293 |
|
|
294 next = prev = CYG_CLASSFROMBASE(Cyg_Thread, |
|
|
295 Cyg_SchedThread_Implementation, |
|
|
296 this); |
|
2
|
297 CYG_REPORT_RETURN(); |
|
0
|
298 } |
|
|
299 |
|
|
300 // ------------------------------------------------------------------------- |
|
|
301 // Insert thread in front of this |
|
|
302 |
|
2
|
303 void |
|
|
304 Cyg_SchedThread_Implementation::insert( Cyg_Thread *thread) |
|
0
|
305 { |
|
|
306 CYG_REPORT_FUNCTION(); |
|
2
|
307 CYG_REPORT_FUNCARG1("thread=%08x", thread); |
|
0
|
308 |
|
|
309 thread->next = CYG_CLASSFROMBASE(Cyg_Thread, |
|
|
310 Cyg_SchedThread_Implementation, |
|
|
311 this); |
|
|
312 thread->prev = prev; |
|
|
313 prev->next = thread; |
|
|
314 prev = thread; |
|
2
|
315 |
|
|
316 CYG_REPORT_RETURN(); |
|
0
|
317 } |
|
|
318 |
|
|
319 // ------------------------------------------------------------------------- |
|
|
320 // remove this from queue |
|
|
321 |
|
2
|
322 void |
|
|
323 Cyg_SchedThread_Implementation::remove(void) |
|
0
|
324 { |
|
|
325 CYG_REPORT_FUNCTION(); |
|
|
326 |
|
|
327 next->prev = prev; |
|
|
328 prev->next = next; |
|
|
329 next = prev = CYG_CLASSFROMBASE(Cyg_Thread, |
|
|
330 Cyg_SchedThread_Implementation, |
|
|
331 this); |
|
2
|
332 CYG_REPORT_RETURN(); |
|
0
|
333 } |
|
|
334 |
|
|
335 // ------------------------------------------------------------------------- |
|
|
336 // Yield the processor to another thread |
|
|
337 |
|
2
|
338 void |
|
|
339 Cyg_SchedThread_Implementation::yield(void) |
|
0
|
340 { |
|
|
341 CYG_REPORT_FUNCTION(); |
|
|
342 |
|
|
343 // Prevent preemption |
|
|
344 Cyg_Scheduler::lock(); |
|
|
345 |
|
|
346 Cyg_Thread *thread = CYG_CLASSFROMBASE(Cyg_Thread, |
|
|
347 Cyg_SchedThread_Implementation, |
|
|
348 this); |
|
|
349 |
|
|
350 // Only do this if this thread is running. If it is not, there |
|
|
351 // is no point. |
|
|
352 |
|
|
353 if( thread->get_state() == Cyg_Thread::RUNNING ) |
|
|
354 { |
|
|
355 // To yield we simply rotate the appropriate |
|
|
356 // run queue to the next thread and reschedule. |
|
|
357 |
|
|
358 CYG_ASSERTCLASS( thread, "Bad current thread"); |
|
|
359 |
|
|
360 Cyg_Scheduler *sched = &Cyg_Scheduler::scheduler; |
|
|
361 |
|
|
362 CYG_ASSERTCLASS( sched, "Bad scheduler"); |
|
|
363 |
|
|
364 cyg_priority pri = thread->priority; |
|
|
365 Cyg_ThreadQueue_Implementation *queue = &sched->run_queue[pri]; |
|
|
366 |
|
|
367 queue->rotate(); |
|
|
368 |
|
|
369 if( queue->highpri() != thread ) |
|
|
370 sched->need_reschedule = true; |
|
|
371 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE |
|
|
372 // Reset the timeslice counter so that this thread gets a full |
|
|
373 // quantum. |
|
|
374 else Cyg_Scheduler::reset_timeslice_count(); |
|
|
375 #endif |
|
|
376 } |
|
|
377 |
|
|
378 // Unlock the scheduler and switch threads |
|
|
379 Cyg_Scheduler::unlock(); |
|
|
380 |
|
2
|
381 CYG_REPORT_RETURN(); |
|
0
|
382 } |
|
|
383 |
|
|
384 // ------------------------------------------------------------------------- |
|
|
385 // Rotate the run queue at a specified priority. |
|
|
386 // (pri is the decider, no this, so the routine is static) |
|
|
387 |
|
|
388 void |
|
|
389 Cyg_SchedThread_Implementation::rotate_queue( cyg_priority pri ) |
|
|
390 { |
|
|
391 CYG_REPORT_FUNCTION(); |
|
2
|
392 CYG_REPORT_FUNCARG1("priority=%d", pri); |
|
0
|
393 |
|
|
394 // Prevent preemption |
|
|
395 Cyg_Scheduler::lock(); |
|
|
396 |
|
|
397 Cyg_Scheduler *sched = &Cyg_Scheduler::scheduler; |
|
|
398 |
|
|
399 CYG_ASSERTCLASS( sched, "Bad scheduler"); |
|
|
400 |
|
|
401 Cyg_ThreadQueue_Implementation *queue = &sched->run_queue[pri]; |
|
|
402 |
|
|
403 if ( !queue->empty() ) { |
|
|
404 queue->rotate(); |
|
|
405 sched->need_reschedule = true; |
|
|
406 } |
|
|
407 |
|
|
408 // Unlock the scheduler and switch threads |
|
|
409 Cyg_Scheduler::unlock(); |
|
|
410 |
|
2
|
411 CYG_REPORT_RETURN(); |
|
|
412 } |
|
|
413 |
|
|
414 // ------------------------------------------------------------------------- |
|
|
415 // Move this thread to the head of its queue |
|
|
416 // (not necessarily a scheduler queue) |
|
|
417 |
|
|
418 void |
|
|
419 Cyg_SchedThread_Implementation::to_queue_head( void ) |
|
|
420 { |
|
|
421 CYG_REPORT_FUNCTION(); |
|
|
422 |
|
|
423 // Prevent preemption |
|
|
424 Cyg_Scheduler::lock(); |
|
|
425 |
|
|
426 Cyg_Thread *thread = CYG_CLASSFROMBASE(Cyg_Thread, |
|
|
427 Cyg_SchedThread_Implementation, |
|
|
428 this); |
|
|
429 |
|
|
430 CYG_ASSERTCLASS( thread, "Bad current thread"); |
|
|
431 |
|
|
432 Cyg_ThreadQueue *q = thread->get_current_queue(); |
|
|
433 q->to_head( thread ); |
|
|
434 |
|
|
435 // Unlock the scheduler and switch threads |
|
|
436 Cyg_Scheduler::unlock(); |
|
|
437 |
|
|
438 CYG_REPORT_RETURN(); |
|
0
|
439 } |
|
|
440 |
|
|
441 //========================================================================== |
|
|
442 // Cyg_ThreadQueue_Implementation class members |
|
|
443 |
|
|
444 Cyg_ThreadQueue_Implementation::Cyg_ThreadQueue_Implementation() |
|
|
445 { |
|
|
446 CYG_REPORT_FUNCTION(); |
|
|
447 |
|
|
448 queue = NULL; // empty queue |
|
2
|
449 |
|
|
450 CYG_REPORT_RETURN(); |
|
0
|
451 } |
|
|
452 |
|
|
453 |
|
|
454 |
|
2
|
455 void |
|
|
456 Cyg_ThreadQueue_Implementation::enqueue(Cyg_Thread *thread) |
|
0
|
457 { |
|
|
458 CYG_REPORT_FUNCTION(); |
|
2
|
459 CYG_REPORT_FUNCARG1("thread=%08x", thread); |
|
0
|
460 |
|
|
461 if( queue == NULL ) queue = thread; |
|
|
462 else queue->insert(thread); |
|
|
463 |
|
|
464 thread->queue = CYG_CLASSFROMBASE(Cyg_ThreadQueue, |
|
|
465 Cyg_ThreadQueue_Implementation, |
|
|
466 this); |
|
2
|
467 CYG_REPORT_RETURN(); |
|
0
|
468 } |
|
|
469 |
|
|
470 // ------------------------------------------------------------------------- |
|
|
471 |
|
2
|
472 Cyg_Thread * |
|
|
473 Cyg_ThreadQueue_Implementation::dequeue(void) |
|
0
|
474 { |
|
2
|
475 CYG_REPORT_FUNCTYPE("returning thread %08x"); |
|
0
|
476 |
|
2
|
477 if( queue == NULL ) { |
|
|
478 CYG_REPORT_RETVAL(NULL); |
|
|
479 return NULL; |
|
|
480 } |
|
0
|
481 |
|
|
482 Cyg_Thread *thread = queue; |
|
|
483 |
|
|
484 if( thread->next == thread ) |
|
|
485 { |
|
|
486 // sole thread on list, NULL out ptr |
|
|
487 queue = NULL; |
|
|
488 } |
|
|
489 else |
|
|
490 { |
|
|
491 // advance to next and remove thread |
|
|
492 queue = thread->next; |
|
|
493 thread->remove(); |
|
|
494 } |
|
|
495 |
|
|
496 thread->queue = NULL; |
|
|
497 |
|
2
|
498 CYG_REPORT_RETVAL(thread); |
|
0
|
499 return thread; |
|
|
500 } |
|
|
501 |
|
|
502 // ------------------------------------------------------------------------- |
|
|
503 |
|
2
|
504 Cyg_Thread * |
|
|
505 Cyg_ThreadQueue_Implementation::highpri(void) |
|
0
|
506 { |
|
2
|
507 CYG_REPORT_FUNCTYPE("returning thread %08x"); |
|
|
508 CYG_REPORT_RETVAL(queue); |
|
0
|
509 return queue; |
|
|
510 } |
|
|
511 |
|
|
512 // ------------------------------------------------------------------------- |
|
|
513 |
|
2
|
514 void |
|
|
515 Cyg_ThreadQueue_Implementation::remove(Cyg_Thread *thread) |
|
0
|
516 { |
|
|
517 CYG_REPORT_FUNCTION(); |
|
2
|
518 CYG_REPORT_FUNCARG1("thread=%08x", thread); |
|
0
|
519 |
|
|
520 // If the thread we want it the at the head |
|
|
521 // of the list, and is on its own, clear the |
|
|
522 // list and return. Otherwise advance to the |
|
|
523 // next thread and remove ours. If the thread |
|
|
524 // is not at the head of the list, just dequeue |
|
|
525 // it. |
|
|
526 |
|
|
527 thread->queue = NULL; |
|
|
528 |
|
|
529 if( queue == thread ) |
|
|
530 { |
|
|
531 if( thread->next == thread ) |
|
|
532 { |
|
|
533 queue = NULL; |
|
|
534 return; |
|
|
535 } |
|
|
536 else queue = thread->next; |
|
|
537 } |
|
|
538 |
|
|
539 thread->Cyg_SchedThread_Implementation::remove(); |
|
|
540 |
|
2
|
541 CYG_REPORT_RETURN(); |
|
0
|
542 } |
|
|
543 |
|
|
544 // ------------------------------------------------------------------------- |
|
|
545 // Rotate the front thread on the queue to the back. |
|
|
546 |
|
2
|
547 void |
|
|
548 Cyg_ThreadQueue_Implementation::rotate(void) |
|
0
|
549 { |
|
|
550 CYG_REPORT_FUNCTION(); |
|
|
551 |
|
|
552 queue = queue->next; |
|
2
|
553 |
|
|
554 CYG_REPORT_RETURN(); |
|
|
555 } |
|
|
556 |
|
|
557 // ------------------------------------------------------------------------- |
|
|
558 // Rotate or move the thread quoted to the front. |
|
|
559 |
|
|
560 void |
|
|
561 Cyg_ThreadQueue_Implementation::to_head(Cyg_Thread *thread) |
|
|
562 { |
|
|
563 CYG_REPORT_FUNCTION(); |
|
|
564 |
|
|
565 queue = thread; |
|
|
566 |
|
|
567 CYG_REPORT_RETURN(); |
|
0
|
568 } |
|
|
569 |
|
|
570 // ------------------------------------------------------------------------- |
|
|
571 |
|
|
572 #endif |
|
|
573 |
|
|
574 // ------------------------------------------------------------------------- |
|
|
575 // EOF sched/mlqueue.cxx |