Rev 378 | Rev 414 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 378 | Rev 413 | ||
---|---|---|---|
Line 123... | Line 123... | ||
123 | int i, n; |
123 | int i, n; |
124 | 124 | ||
125 | ASSERT(CPU != NULL); |
125 | ASSERT(CPU != NULL); |
126 | 126 | ||
127 | loop: |
127 | loop: |
128 | cpu_priority_high(); |
128 | interrupts_disable(); |
129 | 129 | ||
130 | spinlock_lock(&CPU->lock); |
130 | spinlock_lock(&CPU->lock); |
131 | n = CPU->nrdy; |
131 | n = CPU->nrdy; |
132 | spinlock_unlock(&CPU->lock); |
132 | spinlock_unlock(&CPU->lock); |
133 | 133 | ||
134 | cpu_priority_low(); |
134 | interrupts_enable(); |
135 | 135 | ||
136 | if (n == 0) { |
136 | if (n == 0) { |
137 | #ifdef __SMP__ |
137 | #ifdef __SMP__ |
138 | /* |
138 | /* |
139 | * If the load balancing thread is not running, wake it up and |
139 | * If the load balancing thread is not running, wake it up and |
Line 153... | Line 153... | ||
153 | */ |
153 | */ |
154 | cpu_sleep(); |
154 | cpu_sleep(); |
155 | goto loop; |
155 | goto loop; |
156 | } |
156 | } |
157 | 157 | ||
158 | cpu_priority_high(); |
158 | interrupts_disable(); |
159 | 159 | ||
160 | i = 0; |
160 | i = 0; |
161 | retry: |
161 | retry: |
162 | for (; i<RQ_COUNT; i++) { |
162 | for (; i<RQ_COUNT; i++) { |
163 | r = &CPU->rq[i]; |
163 | r = &CPU->rq[i]; |
Line 194... | Line 194... | ||
194 | 194 | ||
195 | spinlock_lock(&t->lock); |
195 | spinlock_lock(&t->lock); |
196 | t->cpu = CPU; |
196 | t->cpu = CPU; |
197 | 197 | ||
198 | t->ticks = us2ticks((i+1)*10000); |
198 | t->ticks = us2ticks((i+1)*10000); |
199 | t->pri = i; /* eventually correct rq index */ |
199 | t->priority = i; /* eventually correct rq index */ |
200 | 200 | ||
201 | /* |
201 | /* |
202 | * Clear the X_STOLEN flag so that t can be migrated when load balancing needs emerge. |
202 | * Clear the X_STOLEN flag so that t can be migrated when load balancing needs emerge. |
203 | */ |
203 | */ |
204 | t->flags &= ~X_STOLEN; |
204 | t->flags &= ~X_STOLEN; |
Line 259... | Line 259... | ||
259 | * The thread scheduling procedure. |
259 | * The thread scheduling procedure. |
260 | * |
260 | * |
261 | */ |
261 | */ |
262 | void scheduler(void) |
262 | void scheduler(void) |
263 | { |
263 | { |
264 | volatile pri_t pri; |
264 | volatile ipl_t ipl; |
265 | 265 | ||
266 | ASSERT(CPU != NULL); |
266 | ASSERT(CPU != NULL); |
267 | 267 | ||
268 | pri = cpu_priority_high(); |
268 | ipl = interrupts_disable(); |
269 | 269 | ||
270 | if (haltstate) |
270 | if (haltstate) |
271 | halt(); |
271 | halt(); |
272 | 272 | ||
273 | if (THREAD) { |
273 | if (THREAD) { |
Line 279... | Line 279... | ||
279 | /* |
279 | /* |
280 | * This is the place where threads leave scheduler(); |
280 | * This is the place where threads leave scheduler(); |
281 | */ |
281 | */ |
282 | before_thread_runs(); |
282 | before_thread_runs(); |
283 | spinlock_unlock(&THREAD->lock); |
283 | spinlock_unlock(&THREAD->lock); |
284 | cpu_priority_restore(THREAD->saved_context.pri); |
284 | interrupts_restore(THREAD->saved_context.ipl); |
285 | return; |
285 | return; |
286 | } |
286 | } |
287 | 287 | ||
288 | /* |
288 | /* |
289 | * CPU priority of preempted thread is recorded here |
289 | * Interrupt priority level of preempted thread is recorded here |
290 | * to facilitate scheduler() invocations from |
290 | * to facilitate scheduler() invocations from interrupts_disable()'d |
291 | * cpu_priority_high()'ed code (e.g. waitq_sleep_timeout()). |
291 | * code (e.g. waitq_sleep_timeout()). |
292 | */ |
292 | */ |
293 | THREAD->saved_context.pri = pri; |
293 | THREAD->saved_context.ipl = ipl; |
294 | } |
294 | } |
295 | 295 | ||
296 | /* |
296 | /* |
297 | * Through the 'THE' structure, we keep track of THREAD, TASK, CPU |
297 | * Through the 'THE' structure, we keep track of THREAD, TASK, CPU |
298 | * and preemption counter. At this point THE could be coming either |
298 | * and preemption counter. At this point THE could be coming either |
Line 369... | Line 369... | ||
369 | 369 | ||
370 | case Sleeping: |
370 | case Sleeping: |
371 | /* |
371 | /* |
372 | * Prefer the thread after it's woken up. |
372 | * Prefer the thread after it's woken up. |
373 | */ |
373 | */ |
374 | THREAD->pri = -1; |
374 | THREAD->priority = -1; |
375 | 375 | ||
376 | /* |
376 | /* |
377 | * We need to release wq->lock which we locked in waitq_sleep(). |
377 | * We need to release wq->lock which we locked in waitq_sleep(). |
378 | * Address of wq->lock is kept in THREAD->sleep_queue. |
378 | * Address of wq->lock is kept in THREAD->sleep_queue. |
379 | */ |
379 | */ |
Line 404... | Line 404... | ||
404 | 404 | ||
405 | 405 | ||
406 | THREAD = find_best_thread(); |
406 | THREAD = find_best_thread(); |
407 | 407 | ||
408 | spinlock_lock(&THREAD->lock); |
408 | spinlock_lock(&THREAD->lock); |
409 | priority = THREAD->pri; |
409 | priority = THREAD->priority; |
410 | spinlock_unlock(&THREAD->lock); |
410 | spinlock_unlock(&THREAD->lock); |
411 | 411 | ||
412 | relink_rq(priority); |
412 | relink_rq(priority); |
413 | 413 | ||
414 | spinlock_lock(&THREAD->lock); |
414 | spinlock_lock(&THREAD->lock); |
Line 444... | Line 444... | ||
444 | } |
444 | } |
445 | 445 | ||
446 | THREAD->state = Running; |
446 | THREAD->state = Running; |
447 | 447 | ||
448 | #ifdef SCHEDULER_VERBOSE |
448 | #ifdef SCHEDULER_VERBOSE |
449 | printf("cpu%d: tid %d (pri=%d,ticks=%d,nrdy=%d)\n", CPU->id, THREAD->tid, THREAD->pri, THREAD->ticks, CPU->nrdy); |
449 | printf("cpu%d: tid %d (priority=%d,ticks=%d,nrdy=%d)\n", CPU->id, THREAD->tid, THREAD->priority, THREAD->ticks, CPU->nrdy); |
450 | #endif |
450 | #endif |
451 | 451 | ||
452 | /* |
452 | /* |
453 | * Copy the knowledge of CPU, TASK, THREAD and preemption counter to thread's stack. |
453 | * Copy the knowledge of CPU, TASK, THREAD and preemption counter to thread's stack. |
454 | */ |
454 | */ |
Line 470... | Line 470... | ||
470 | */ |
470 | */ |
471 | void kcpulb(void *arg) |
471 | void kcpulb(void *arg) |
472 | { |
472 | { |
473 | thread_t *t; |
473 | thread_t *t; |
474 | int count, i, j, k = 0; |
474 | int count, i, j, k = 0; |
475 | pri_t pri; |
475 | ipl_t ipl; |
476 | 476 | ||
477 | loop: |
477 | loop: |
478 | /* |
478 | /* |
479 | * Sleep until there's some work to do. |
479 | * Sleep until there's some work to do. |
480 | */ |
480 | */ |
Line 484... | Line 484... | ||
484 | /* |
484 | /* |
485 | * Calculate the number of threads that will be migrated/stolen from |
485 | * Calculate the number of threads that will be migrated/stolen from |
486 | * other CPU's. Note that situation can have changed between two |
486 | * other CPU's. Note that situation can have changed between two |
487 | * passes. Each time get the most up to date counts. |
487 | * passes. Each time get the most up to date counts. |
488 | */ |
488 | */ |
489 | pri = cpu_priority_high(); |
489 | ipl = interrupts_disable(); |
490 | spinlock_lock(&CPU->lock); |
490 | spinlock_lock(&CPU->lock); |
491 | count = nrdy / config.cpu_active; |
491 | count = nrdy / config.cpu_active; |
492 | count -= CPU->nrdy; |
492 | count -= CPU->nrdy; |
493 | spinlock_unlock(&CPU->lock); |
493 | spinlock_unlock(&CPU->lock); |
494 | cpu_priority_restore(pri); |
494 | interrupts_restore(ipl); |
495 | 495 | ||
496 | if (count <= 0) |
496 | if (count <= 0) |
497 | goto satisfied; |
497 | goto satisfied; |
498 | 498 | ||
499 | /* |
499 | /* |
Line 512... | Line 512... | ||
512 | * Doesn't require interrupt disabling for kcpulb is X_WIRED. |
512 | * Doesn't require interrupt disabling for kcpulb is X_WIRED. |
513 | */ |
513 | */ |
514 | if (CPU == cpu) |
514 | if (CPU == cpu) |
515 | continue; |
515 | continue; |
516 | 516 | ||
517 | restart: pri = cpu_priority_high(); |
517 | restart: ipl = interrupts_disable(); |
518 | r = &cpu->rq[j]; |
518 | r = &cpu->rq[j]; |
519 | spinlock_lock(&r->lock); |
519 | spinlock_lock(&r->lock); |
520 | if (r->n == 0) { |
520 | if (r->n == 0) { |
521 | spinlock_unlock(&r->lock); |
521 | spinlock_unlock(&r->lock); |
522 | cpu_priority_restore(pri); |
522 | interrupts_restore(ipl); |
523 | continue; |
523 | continue; |
524 | } |
524 | } |
525 | 525 | ||
526 | t = NULL; |
526 | t = NULL; |
527 | l = r->rq_head.prev; /* search rq from the back */ |
527 | l = r->rq_head.prev; /* search rq from the back */ |
Line 546... | Line 546... | ||
546 | * because it locks cpu and r in a different order than we do. |
546 | * because it locks cpu and r in a different order than we do. |
547 | */ |
547 | */ |
548 | if (!spinlock_trylock(&cpu->lock)) { |
548 | if (!spinlock_trylock(&cpu->lock)) { |
549 | /* Release all locks and try again. */ |
549 | /* Release all locks and try again. */ |
550 | spinlock_unlock(&r->lock); |
550 | spinlock_unlock(&r->lock); |
551 | cpu_priority_restore(pri); |
551 | interrupts_restore(ipl); |
552 | goto restart; |
552 | goto restart; |
553 | } |
553 | } |
554 | cpu->nrdy--; |
554 | cpu->nrdy--; |
555 | spinlock_unlock(&cpu->lock); |
555 | spinlock_unlock(&cpu->lock); |
556 | 556 | ||
Line 578... | Line 578... | ||
578 | t->flags |= X_STOLEN; |
578 | t->flags |= X_STOLEN; |
579 | spinlock_unlock(&t->lock); |
579 | spinlock_unlock(&t->lock); |
580 | 580 | ||
581 | thread_ready(t); |
581 | thread_ready(t); |
582 | 582 | ||
583 | cpu_priority_restore(pri); |
583 | interrupts_restore(ipl); |
584 | 584 | ||
585 | if (--count == 0) |
585 | if (--count == 0) |
586 | goto satisfied; |
586 | goto satisfied; |
587 | 587 | ||
588 | /* |
588 | /* |
Line 590... | Line 590... | ||
590 | */ |
590 | */ |
591 | k++; |
591 | k++; |
592 | 592 | ||
593 | continue; |
593 | continue; |
594 | } |
594 | } |
595 | cpu_priority_restore(pri); |
595 | interrupts_restore(ipl); |
596 | } |
596 | } |
597 | } |
597 | } |
598 | 598 | ||
599 | if (CPU->nrdy) { |
599 | if (CPU->nrdy) { |
600 | /* |
600 | /* |