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