Rev 2292 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2292 | Rev 2307 | ||
|---|---|---|---|
| Line 59... | Line 59... | ||
| 59 | #include <adt/list.h> |
59 | #include <adt/list.h> |
| 60 | #include <panic.h> |
60 | #include <panic.h> |
| 61 | #include <cpu.h> |
61 | #include <cpu.h> |
| 62 | #include <print.h> |
62 | #include <print.h> |
| 63 | #include <debug.h> |
63 | #include <debug.h> |
| - | 64 | #include <synch/rcu.h> |
|
| 64 | 65 | ||
| 65 | static void before_task_runs(void); |
66 | static void before_task_runs(void); |
| 66 | static void before_thread_runs(void); |
67 | static void before_thread_runs(void); |
| 67 | static void after_thread_ran(void); |
68 | static void after_thread_ran(void); |
| 68 | static void scheduler_separated_stack(void); |
69 | static void scheduler_separated_stack(void); |
| Line 113... | Line 114... | ||
| 113 | * |
114 | * |
| 114 | */ |
115 | */ |
| 115 | void after_thread_ran(void) |
116 | void after_thread_ran(void) |
| 116 | { |
117 | { |
| 117 | after_thread_ran_arch(); |
118 | after_thread_ran_arch(); |
| - | 119 | rcu_run_callbacks(); |
|
| 118 | } |
120 | } |
| 119 | 121 | ||
| 120 | #ifdef CONFIG_FPU_LAZY |
122 | #ifdef CONFIG_FPU_LAZY |
| 121 | void scheduler_fpu_lazy_request(void) |
123 | void scheduler_fpu_lazy_request(void) |
| 122 | { |
124 | { |
| Line 205... | Line 207... | ||
| 205 | goto loop; |
207 | goto loop; |
| 206 | } |
208 | } |
| 207 | 209 | ||
| 208 | interrupts_disable(); |
210 | interrupts_disable(); |
| 209 | 211 | ||
| 210 | for (i = 0; i<RQ_COUNT; i++) { |
212 | for (i = 0; i < RQ_COUNT; i++) { |
| 211 | r = &CPU->rq[i]; |
213 | r = &CPU->rq[i]; |
| 212 | spinlock_lock(&r->lock); |
214 | spinlock_lock(&r->lock); |
| 213 | if (r->n == 0) { |
215 | if (r->n == 0) { |
| 214 | /* |
216 | /* |
| 215 | * If this queue is empty, try a lower-priority queue. |
217 | * If this queue is empty, try a lower-priority queue. |
| Line 375... | Line 377... | ||
| 375 | * Assume THREAD->lock is held. |
377 | * Assume THREAD->lock is held. |
| 376 | */ |
378 | */ |
| 377 | void scheduler_separated_stack(void) |
379 | void scheduler_separated_stack(void) |
| 378 | { |
380 | { |
| 379 | int priority; |
381 | int priority; |
| - | 382 | DEADLOCK_PROBE_INIT(p_joinwq); |
|
| 380 | 383 | ||
| 381 | ASSERT(CPU != NULL); |
384 | ASSERT(CPU != NULL); |
| 382 | 385 | ||
| 383 | if (THREAD) { |
386 | if (THREAD) { |
| 384 | /* must be run after the switch to scheduler stack */ |
387 | /* must be run after the switch to scheduler stack */ |
| 385 | after_thread_ran(); |
388 | after_thread_ran(); |
| Line 404... | Line 407... | ||
| 404 | * Avoid deadlock. |
407 | * Avoid deadlock. |
| 405 | */ |
408 | */ |
| 406 | spinlock_unlock(&THREAD->lock); |
409 | spinlock_unlock(&THREAD->lock); |
| 407 | delay(10); |
410 | delay(10); |
| 408 | spinlock_lock(&THREAD->lock); |
411 | spinlock_lock(&THREAD->lock); |
| - | 412 | DEADLOCK_PROBE(p_joinwq, |
|
| - | 413 | DEADLOCK_THRESHOLD); |
|
| 409 | goto repeat; |
414 | goto repeat; |
| 410 | } |
415 | } |
| 411 | _waitq_wakeup_unsafe(&THREAD->join_wq, false); |
416 | _waitq_wakeup_unsafe(&THREAD->join_wq, false); |
| 412 | spinlock_unlock(&THREAD->join_wq.lock); |
417 | spinlock_unlock(&THREAD->join_wq.lock); |
| 413 | 418 | ||
| Line 445... | Line 450... | ||
| 445 | 450 | ||
| 446 | default: |
451 | default: |
| 447 | /* |
452 | /* |
| 448 | * Entering state is unexpected. |
453 | * Entering state is unexpected. |
| 449 | */ |
454 | */ |
| 450 | panic("tid%d: unexpected state %s\n", THREAD->tid, |
455 | panic("tid%llu: unexpected state %s\n", THREAD->tid, |
| 451 | thread_states[THREAD->state]); |
456 | thread_states[THREAD->state]); |
| 452 | break; |
457 | break; |
| 453 | } |
458 | } |
| 454 | 459 | ||
| 455 | THREAD = NULL; |
460 | THREAD = NULL; |
| 456 | } |
461 | } |
| Line 498... | Line 503... | ||
| 498 | 503 | ||
| 499 | spinlock_lock(&THREAD->lock); |
504 | spinlock_lock(&THREAD->lock); |
| 500 | THREAD->state = Running; |
505 | THREAD->state = Running; |
| 501 | 506 | ||
| 502 | #ifdef SCHEDULER_VERBOSE |
507 | #ifdef SCHEDULER_VERBOSE |
| 503 | printf("cpu%d: tid %d (priority=%d, ticks=%lld, nrdy=%ld)\n", |
508 | printf("cpu%d: tid %llu (priority=%d, ticks=%llu, nrdy=%ld)\n", |
| 504 | CPU->id, THREAD->tid, THREAD->priority, THREAD->ticks, |
509 | CPU->id, THREAD->tid, THREAD->priority, THREAD->ticks, |
| 505 | atomic_get(&CPU->nrdy)); |
510 | atomic_get(&CPU->nrdy)); |
| 506 | #endif |
511 | #endif |
| 507 | 512 | ||
| 508 | /* |
513 | /* |
| Line 566... | Line 571... | ||
| 566 | 571 | ||
| 567 | /* |
572 | /* |
| 568 | * Searching least priority queues on all CPU's first and most priority |
573 | * Searching least priority queues on all CPU's first and most priority |
| 569 | * queues on all CPU's last. |
574 | * queues on all CPU's last. |
| 570 | */ |
575 | */ |
| 571 | for (j= RQ_COUNT - 1; j >= 0; j--) { |
576 | for (j = RQ_COUNT - 1; j >= 0; j--) { |
| 572 | for (i = 0; i < config.cpu_active; i++) { |
577 | for (i = 0; i < config.cpu_active; i++) { |
| 573 | link_t *l; |
578 | link_t *l; |
| 574 | runq_t *r; |
579 | runq_t *r; |
| 575 | cpu_t *cpu; |
580 | cpu_t *cpu; |
| 576 | 581 | ||
| Line 607... | Line 612... | ||
| 607 | * steal threads whose FPU context is still in |
612 | * steal threads whose FPU context is still in |
| 608 | * CPU. |
613 | * CPU. |
| 609 | */ |
614 | */ |
| 610 | spinlock_lock(&t->lock); |
615 | spinlock_lock(&t->lock); |
| 611 | if ((!(t->flags & (THREAD_FLAG_WIRED | |
616 | if ((!(t->flags & (THREAD_FLAG_WIRED | |
| 612 | THREAD_FLAG_STOLEN))) && |
617 | THREAD_FLAG_STOLEN))) && |
| 613 | (!(t->fpu_context_engaged)) ) { |
618 | (!(t->fpu_context_engaged))) { |
| 614 | /* |
619 | /* |
| 615 | * Remove t from r. |
620 | * Remove t from r. |
| 616 | */ |
621 | */ |
| 617 | spinlock_unlock(&t->lock); |
622 | spinlock_unlock(&t->lock); |
| 618 | 623 | ||
| Line 634... | Line 639... | ||
| 634 | /* |
639 | /* |
| 635 | * Ready t on local CPU |
640 | * Ready t on local CPU |
| 636 | */ |
641 | */ |
| 637 | spinlock_lock(&t->lock); |
642 | spinlock_lock(&t->lock); |
| 638 | #ifdef KCPULB_VERBOSE |
643 | #ifdef KCPULB_VERBOSE |
| 639 | printf("kcpulb%d: TID %d -> cpu%d, nrdy=%ld, " |
644 | printf("kcpulb%d: TID %llu -> cpu%d, nrdy=%ld, " |
| 640 | "avg=%nd\n", CPU->id, t->tid, CPU->id, |
645 | "avg=%nd\n", CPU->id, t->tid, CPU->id, |
| 641 | atomic_get(&CPU->nrdy), |
646 | atomic_get(&CPU->nrdy), |
| 642 | atomic_get(&nrdy) / config.cpu_active); |
647 | atomic_get(&nrdy) / config.cpu_active); |
| 643 | #endif |
648 | #endif |
| 644 | t->flags |= THREAD_FLAG_STOLEN; |
649 | t->flags |= THREAD_FLAG_STOLEN; |
| Line 717... | Line 722... | ||
| 717 | } |
722 | } |
| 718 | printf("\trq[%d]: ", i); |
723 | printf("\trq[%d]: ", i); |
| 719 | for (cur = r->rq_head.next; cur != &r->rq_head; |
724 | for (cur = r->rq_head.next; cur != &r->rq_head; |
| 720 | cur = cur->next) { |
725 | cur = cur->next) { |
| 721 | t = list_get_instance(cur, thread_t, rq_link); |
726 | t = list_get_instance(cur, thread_t, rq_link); |
| 722 | printf("%d(%s) ", t->tid, |
727 | printf("%llu(%s) ", t->tid, |
| 723 | thread_states[t->state]); |
728 | thread_states[t->state]); |
| 724 | } |
729 | } |
| 725 | printf("\n"); |
730 | printf("\n"); |
| 726 | spinlock_unlock(&r->lock); |
731 | spinlock_unlock(&r->lock); |
| 727 | } |
732 | } |