Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/proc/scheduler.c

    rdf58e44 r98000fb  
    11/*
    2  * Copyright (c) 2010 Jakub Jermar
     2 * Copyright (c) 2001-2007 Jakub Jermar
    33 * All rights reserved.
    44 *
     
    3333/**
    3434 * @file
    35  * @brief Scheduler and load balancing.
     35 * @brief       Scheduler and load balancing.
    3636 *
    3737 * This file contains the scheduler and kcpulb kernel thread which
     
    6262#include <print.h>
    6363#include <debug.h>
    64 #include <stacktrace.h>
    65 
     64
     65static void before_task_runs(void);
     66static void before_thread_runs(void);
     67static void after_thread_ran(void);
    6668static void scheduler_separated_stack(void);
    6769
    68 atomic_t nrdy;  /**< Number of ready threads in the system. */
     70atomic_t nrdy;  /**< Number of ready threads in the system. */
    6971
    7072/** Carry out actions before new task runs. */
    71 static void before_task_runs(void)
     73void before_task_runs(void)
    7274{
    7375        before_task_runs_arch();
     
    7880 * Perform actions that need to be
    7981 * taken before the newly selected
    80  * thread is passed control.
     82 * tread is passed control.
    8183 *
    8284 * THREAD->lock is locked on entry
    8385 *
    8486 */
    85 static void before_thread_runs(void)
     87void before_thread_runs(void)
    8688{
    8789        before_thread_runs_arch();
    88        
    8990#ifdef CONFIG_FPU_LAZY
    90         if (THREAD == CPU->fpu_owner)
     91        if(THREAD == CPU->fpu_owner)
    9192                fpu_enable();
    9293        else
    93                 fpu_disable();
     94                fpu_disable(); 
    9495#else
    9596        fpu_enable();
     
    101102        }
    102103#endif
    103        
    104         if (THREAD->btrace) {
    105                 istate_t *istate = THREAD->udebug.uspace_state;
    106                 if (istate != NULL) {
    107                         printf("Thread %" PRIu64 " stack trace:\n", THREAD->tid);
    108                         stack_trace_istate(istate);
    109                 }
    110                
    111                 THREAD->btrace = false;
    112         }
    113104}
    114105
     
    122113 *
    123114 */
    124 static void after_thread_ran(void)
     115void after_thread_ran(void)
    125116{
    126117        after_thread_ran_arch();
     
    132123restart:
    133124        fpu_enable();
    134         irq_spinlock_lock(&CPU->lock, false);
    135        
     125        spinlock_lock(&CPU->lock);
     126
    136127        /* Save old context */
    137         if (CPU->fpu_owner != NULL) {
    138                 irq_spinlock_lock(&CPU->fpu_owner->lock, false);
     128        if (CPU->fpu_owner != NULL) { 
     129                spinlock_lock(&CPU->fpu_owner->lock);
    139130                fpu_context_save(CPU->fpu_owner->saved_fpu_context);
    140                
    141                 /* Don't prevent migration */
     131                /* don't prevent migration */
    142132                CPU->fpu_owner->fpu_context_engaged = 0;
    143                 irq_spinlock_unlock(&CPU->fpu_owner->lock, false);
     133                spinlock_unlock(&CPU->fpu_owner->lock);
    144134                CPU->fpu_owner = NULL;
    145135        }
    146        
    147         irq_spinlock_lock(&THREAD->lock, false);
     136
     137        spinlock_lock(&THREAD->lock);
    148138        if (THREAD->fpu_context_exists) {
    149139                fpu_context_restore(THREAD->saved_fpu_context);
     
    152142                if (!THREAD->saved_fpu_context) {
    153143                        /* Might sleep */
    154                         irq_spinlock_unlock(&THREAD->lock, false);
    155                         irq_spinlock_unlock(&CPU->lock, false);
     144                        spinlock_unlock(&THREAD->lock);
     145                        spinlock_unlock(&CPU->lock);
    156146                        THREAD->saved_fpu_context =
    157147                            (fpu_context_t *) slab_alloc(fpu_context_slab, 0);
    158                        
    159148                        /* We may have switched CPUs during slab_alloc */
    160                         goto restart;
     149                        goto restart; 
    161150                }
    162151                fpu_init();
    163152                THREAD->fpu_context_exists = 1;
    164153        }
    165        
    166154        CPU->fpu_owner = THREAD;
    167155        THREAD->fpu_context_engaged = 1;
    168         irq_spinlock_unlock(&THREAD->lock, false);
    169        
    170         irq_spinlock_unlock(&CPU->lock, false);
    171 }
    172 #endif /* CONFIG_FPU_LAZY */
     156        spinlock_unlock(&THREAD->lock);
     157
     158        spinlock_unlock(&CPU->lock);
     159}
     160#endif
    173161
    174162/** Initialize scheduler
     
    192180static thread_t *find_best_thread(void)
    193181{
     182        thread_t *t;
     183        runq_t *r;
     184        int i;
     185
    194186        ASSERT(CPU != NULL);
    195        
     187
    196188loop:
     189        interrupts_enable();
    197190       
    198191        if (atomic_get(&CPU->nrdy) == 0) {
     
    202195                 * This improves energy saving and hyperthreading.
    203196                 */
    204                 irq_spinlock_lock(&CPU->lock, false);
    205                 CPU->idle = true;
    206                 irq_spinlock_unlock(&CPU->lock, false);
    207                 interrupts_enable();
    208                
     197
    209198                /*
    210199                 * An interrupt might occur right now and wake up a thread.
     
    212201                 * even though there is a runnable thread.
    213202                 */
    214                 cpu_sleep();
    215                 interrupts_disable();
    216                 goto loop;
    217         }
    218        
    219         unsigned int i;
     203
     204                 cpu_sleep();
     205                 goto loop;
     206        }
     207
     208        interrupts_disable();
     209       
    220210        for (i = 0; i < RQ_COUNT; i++) {
    221                 irq_spinlock_lock(&(CPU->rq[i].lock), false);
    222                 if (CPU->rq[i].n == 0) {
     211                r = &CPU->rq[i];
     212                spinlock_lock(&r->lock);
     213                if (r->n == 0) {
    223214                        /*
    224215                         * If this queue is empty, try a lower-priority queue.
    225216                         */
    226                         irq_spinlock_unlock(&(CPU->rq[i].lock), false);
     217                        spinlock_unlock(&r->lock);
    227218                        continue;
    228219                }
    229                
     220
    230221                atomic_dec(&CPU->nrdy);
    231222                atomic_dec(&nrdy);
    232                 CPU->rq[i].n--;
    233                
     223                r->n--;
     224
    234225                /*
    235226                 * Take the first thread from the queue.
    236227                 */
    237                 thread_t *thread =
    238                     list_get_instance(CPU->rq[i].rq_head.next, thread_t, rq_link);
    239                 list_remove(&thread->rq_link);
    240                
    241                 irq_spinlock_pass(&(CPU->rq[i].lock), &thread->lock);
    242                
    243                 thread->cpu = CPU;
    244                 thread->ticks = us2ticks((i + 1) * 10000);
    245                 thread->priority = i;  /* Correct rq index */
    246                
     228                t = list_get_instance(r->rq_head.next, thread_t, rq_link);
     229                list_remove(&t->rq_link);
     230
     231                spinlock_unlock(&r->lock);
     232
     233                spinlock_lock(&t->lock);
     234                t->cpu = CPU;
     235
     236                t->ticks = us2ticks((i + 1) * 10000);
     237                t->priority = i;        /* correct rq index */
     238
    247239                /*
    248240                 * Clear the THREAD_FLAG_STOLEN flag so that t can be migrated
    249241                 * when load balancing needs emerge.
    250242                 */
    251                 thread->flags &= ~THREAD_FLAG_STOLEN;
    252                 irq_spinlock_unlock(&thread->lock, false);
    253                
    254                 return thread;
    255         }
    256        
     243                t->flags &= ~THREAD_FLAG_STOLEN;
     244                spinlock_unlock(&t->lock);
     245
     246                return t;
     247        }
    257248        goto loop;
     249
    258250}
    259251
     
    272264{
    273265        link_t head;
    274        
     266        runq_t *r;
     267        int i, n;
     268
    275269        list_initialize(&head);
    276         irq_spinlock_lock(&CPU->lock, false);
    277        
     270        spinlock_lock(&CPU->lock);
    278271        if (CPU->needs_relink > NEEDS_RELINK_MAX) {
    279                 int i;
    280272                for (i = start; i < RQ_COUNT - 1; i++) {
    281                         /* Remember and empty rq[i + 1] */
    282                        
    283                         irq_spinlock_lock(&CPU->rq[i + 1].lock, false);
    284                         list_concat(&head, &CPU->rq[i + 1].rq_head);
    285                         size_t n = CPU->rq[i + 1].n;
    286                         CPU->rq[i + 1].n = 0;
    287                         irq_spinlock_unlock(&CPU->rq[i + 1].lock, false);
    288                        
    289                         /* Append rq[i + 1] to rq[i] */
    290                        
    291                         irq_spinlock_lock(&CPU->rq[i].lock, false);
    292                         list_concat(&CPU->rq[i].rq_head, &head);
    293                         CPU->rq[i].n += n;
    294                         irq_spinlock_unlock(&CPU->rq[i].lock, false);
    295                 }
     273                        /* remember and empty rq[i + 1] */
     274                        r = &CPU->rq[i + 1];
     275                        spinlock_lock(&r->lock);
     276                        list_concat(&head, &r->rq_head);
     277                        n = r->n;
     278                        r->n = 0;
     279                        spinlock_unlock(&r->lock);
    296280               
     281                        /* append rq[i + 1] to rq[i] */
     282                        r = &CPU->rq[i];
     283                        spinlock_lock(&r->lock);
     284                        list_concat(&r->rq_head, &head);
     285                        r->n += n;
     286                        spinlock_unlock(&r->lock);
     287                }
    297288                CPU->needs_relink = 0;
    298289        }
    299        
    300         irq_spinlock_unlock(&CPU->lock, false);
     290        spinlock_unlock(&CPU->lock);
     291
    301292}
    302293
     
    311302{
    312303        volatile ipl_t ipl;
    313        
     304
    314305        ASSERT(CPU != NULL);
    315        
     306
    316307        ipl = interrupts_disable();
    317        
     308
    318309        if (atomic_get(&haltstate))
    319310                halt();
    320311       
    321312        if (THREAD) {
    322                 irq_spinlock_lock(&THREAD->lock, false);
     313                spinlock_lock(&THREAD->lock);
    323314               
    324                 /* Update thread kernel accounting */
    325                 THREAD->kcycles += get_cycle() - THREAD->last_cycle;
     315                /* Update thread accounting */
     316                THREAD->cycles += get_cycle() - THREAD->last_cycle;
    326317               
    327318#ifndef CONFIG_FPU_LAZY
     
    336327                        THREAD->last_cycle = get_cycle();
    337328                       
    338                         irq_spinlock_unlock(&THREAD->lock, false);
     329                        spinlock_unlock(&THREAD->lock);
    339330                        interrupts_restore(THREAD->saved_context.ipl);
    340331                       
    341332                        return;
    342333                }
    343                
     334
    344335                /*
    345336                 * Interrupt priority level of preempted thread is recorded
    346337                 * here to facilitate scheduler() invocations from
    347                  * interrupts_disable()'d code (e.g. waitq_sleep_timeout()).
    348                  *
     338                 * interrupts_disable()'d code (e.g. waitq_sleep_timeout()).
    349339                 */
    350340                THREAD->saved_context.ipl = ipl;
    351341        }
    352        
     342
    353343        /*
    354344         * Through the 'THE' structure, we keep track of THREAD, TASK, CPU, VM
    355345         * and preemption counter. At this point THE could be coming either
    356346         * from THREAD's or CPU's stack.
    357          *
    358347         */
    359348        the_copy(THE, (the_t *) CPU->stack);
    360        
     349
    361350        /*
    362351         * We may not keep the old stack.
     
    370359         * Therefore the scheduler() function continues in
    371360         * scheduler_separated_stack().
    372          *
    373361         */
    374362        context_save(&CPU->saved_context);
     
    376364            (uintptr_t) CPU->stack, CPU_STACK_SIZE);
    377365        context_restore(&CPU->saved_context);
    378        
    379         /* Not reached */
     366        /* not reached */
    380367}
    381368
     
    386373 * switch to a new thread.
    387374 *
     375 * Assume THREAD->lock is held.
    388376 */
    389377void scheduler_separated_stack(void)
    390378{
     379        int priority;
    391380        DEADLOCK_PROBE_INIT(p_joinwq);
    392         task_t *old_task = TASK;
    393         as_t *old_as = AS;
    394        
    395         ASSERT((!THREAD) || (irq_spinlock_locked(&THREAD->lock)));
     381
    396382        ASSERT(CPU != NULL);
    397383       
    398         /*
    399          * Hold the current task and the address space to prevent their
    400          * possible destruction should thread_destroy() be called on this or any
    401          * other processor while the scheduler is still using them.
    402          */
    403         if (old_task)
    404                 task_hold(old_task);
    405        
    406         if (old_as)
    407                 as_hold(old_as);
    408        
    409384        if (THREAD) {
    410                 /* Must be run after the switch to scheduler stack */
     385                /* must be run after the switch to scheduler stack */
    411386                after_thread_ran();
    412                
     387
    413388                switch (THREAD->state) {
    414389                case Running:
    415                         irq_spinlock_unlock(&THREAD->lock, false);
     390                        spinlock_unlock(&THREAD->lock);
    416391                        thread_ready(THREAD);
    417392                        break;
    418                
     393
    419394                case Exiting:
    420395repeat:
    421396                        if (THREAD->detached) {
    422                                 thread_destroy(THREAD, false);
     397                                thread_destroy(THREAD);
    423398                        } else {
    424399                                /*
     
    426401                                 * somebody calls thread_detach() on it.
    427402                                 */
    428                                 if (!irq_spinlock_trylock(&THREAD->join_wq.lock)) {
     403                                if (!spinlock_trylock(&THREAD->join_wq.lock)) {
    429404                                        /*
    430405                                         * Avoid deadlock.
    431406                                         */
    432                                         irq_spinlock_unlock(&THREAD->lock, false);
     407                                        spinlock_unlock(&THREAD->lock);
    433408                                        delay(HZ);
    434                                         irq_spinlock_lock(&THREAD->lock, false);
     409                                        spinlock_lock(&THREAD->lock);
    435410                                        DEADLOCK_PROBE(p_joinwq,
    436411                                            DEADLOCK_THRESHOLD);
     
    439414                                _waitq_wakeup_unsafe(&THREAD->join_wq,
    440415                                    WAKEUP_FIRST);
    441                                 irq_spinlock_unlock(&THREAD->join_wq.lock, false);
     416                                spinlock_unlock(&THREAD->join_wq.lock);
    442417                               
    443418                                THREAD->state = Lingering;
    444                                 irq_spinlock_unlock(&THREAD->lock, false);
     419                                spinlock_unlock(&THREAD->lock);
    445420                        }
    446421                        break;
     
    451426                         */
    452427                        THREAD->priority = -1;
    453                        
     428
    454429                        /*
    455430                         * We need to release wq->lock which we locked in
     
    457432                         * THREAD->sleep_queue.
    458433                         */
    459                         irq_spinlock_unlock(&THREAD->sleep_queue->lock, false);
    460                        
    461                         irq_spinlock_unlock(&THREAD->lock, false);
     434                        spinlock_unlock(&THREAD->sleep_queue->lock);
     435
     436                        /*
     437                         * Check for possible requests for out-of-context
     438                         * invocation.
     439                         */
     440                        if (THREAD->call_me) {
     441                                THREAD->call_me(THREAD->call_me_with);
     442                                THREAD->call_me = NULL;
     443                                THREAD->call_me_with = NULL;
     444                        }
     445
     446                        spinlock_unlock(&THREAD->lock);
     447
    462448                        break;
    463                
     449
    464450                default:
    465451                        /*
     
    470456                        break;
    471457                }
    472                
     458
    473459                THREAD = NULL;
    474460        }
    475        
     461
    476462        THREAD = find_best_thread();
    477463       
    478         irq_spinlock_lock(&THREAD->lock, false);
    479         int priority = THREAD->priority;
    480         irq_spinlock_unlock(&THREAD->lock, false);
    481        
    482         relink_rq(priority);
    483        
    484         /*
    485          * If both the old and the new task are the same,
    486          * lots of work is avoided.
     464        spinlock_lock(&THREAD->lock);
     465        priority = THREAD->priority;
     466        spinlock_unlock(&THREAD->lock);
     467
     468        relink_rq(priority);           
     469
     470        /*
     471         * If both the old and the new task are the same, lots of work is
     472         * avoided.
    487473         */
    488474        if (TASK != THREAD->task) {
    489                 as_t *new_as = THREAD->task->as;
     475                as_t *as1 = NULL;
     476                as_t *as2;
     477
     478                if (TASK) {
     479                        spinlock_lock(&TASK->lock);
     480                        as1 = TASK->as;
     481                        spinlock_unlock(&TASK->lock);
     482                }
     483
     484                spinlock_lock(&THREAD->task->lock);
     485                as2 = THREAD->task->as;
     486                spinlock_unlock(&THREAD->task->lock);
    490487               
    491488                /*
    492                  * Note that it is possible for two tasks
    493                  * to share one address space.
     489                 * Note that it is possible for two tasks to share one address
     490                 * space.
    494491                 */
    495                 if (old_as != new_as) {
     492                if (as1 != as2) {
    496493                        /*
    497494                         * Both tasks and address spaces are different.
    498495                         * Replace the old one with the new one.
    499496                         */
    500                         as_switch(old_as, new_as);
    501                 }
    502                
     497                        as_switch(as1, as2);
     498                }
    503499                TASK = THREAD->task;
    504500                before_task_runs();
    505501        }
    506        
    507         if (old_task)
    508                 task_release(old_task);
    509        
    510         if (old_as)
    511                 as_release(old_as);
    512        
    513         irq_spinlock_lock(&THREAD->lock, false);
     502
     503        spinlock_lock(&THREAD->lock);   
    514504        THREAD->state = Running;
    515        
     505
    516506#ifdef SCHEDULER_VERBOSE
    517507        printf("cpu%u: tid %" PRIu64 " (priority=%d, ticks=%" PRIu64
    518508            ", nrdy=%ld)\n", CPU->id, THREAD->tid, THREAD->priority,
    519509            THREAD->ticks, atomic_get(&CPU->nrdy));
    520 #endif
    521        
     510#endif 
     511
    522512        /*
    523513         * Some architectures provide late kernel PA2KA(identity)
     
    529519         */
    530520        before_thread_runs();
    531        
     521
    532522        /*
    533523         * Copy the knowledge of CPU, TASK, THREAD and preemption counter to
     
    537527       
    538528        context_restore(&THREAD->saved_context);
    539        
    540         /* Not reached */
     529        /* not reached */
    541530}
    542531
     
    552541void kcpulb(void *arg)
    553542{
    554         atomic_count_t average;
    555         atomic_count_t rdy;
    556        
     543        thread_t *t;
     544        int count, average, j, k = 0;
     545        unsigned int i;
     546        ipl_t ipl;
     547
    557548        /*
    558549         * Detach kcpulb as nobody will call thread_join_timeout() on it.
     
    565556         */
    566557        thread_sleep(1);
    567        
     558
    568559not_satisfied:
    569560        /*
     
    571562         * other CPU's. Note that situation can have changed between two
    572563         * passes. Each time get the most up to date counts.
    573          *
    574564         */
    575565        average = atomic_get(&nrdy) / config.cpu_active + 1;
    576         rdy = atomic_get(&CPU->nrdy);
    577        
    578         if (average <= rdy)
     566        count = average - atomic_get(&CPU->nrdy);
     567
     568        if (count <= 0)
    579569                goto satisfied;
    580        
    581         atomic_count_t count = average - rdy;
    582        
     570
    583571        /*
    584572         * Searching least priority queues on all CPU's first and most priority
    585573         * queues on all CPU's last.
    586          *
    587          */
    588         size_t acpu;
    589         size_t acpu_bias = 0;
    590         int rq;
    591        
    592         for (rq = RQ_COUNT - 1; rq >= 0; rq--) {
    593                 for (acpu = 0; acpu < config.cpu_active; acpu++) {
    594                         cpu_t *cpu = &cpus[(acpu + acpu_bias) % config.cpu_active];
    595                        
     574         */
     575        for (j = RQ_COUNT - 1; j >= 0; j--) {
     576                for (i = 0; i < config.cpu_active; i++) {
     577                        link_t *l;
     578                        runq_t *r;
     579                        cpu_t *cpu;
     580
     581                        cpu = &cpus[(i + k) % config.cpu_active];
     582
    596583                        /*
    597584                         * Not interested in ourselves.
    598585                         * Doesn't require interrupt disabling for kcpulb has
    599586                         * THREAD_FLAG_WIRED.
    600                          *
    601587                         */
    602588                        if (CPU == cpu)
    603589                                continue;
    604                        
    605590                        if (atomic_get(&cpu->nrdy) <= average)
    606591                                continue;
    607                        
    608                         irq_spinlock_lock(&(cpu->rq[rq].lock), true);
    609                         if (cpu->rq[rq].n == 0) {
    610                                 irq_spinlock_unlock(&(cpu->rq[rq].lock), true);
     592
     593                        ipl = interrupts_disable();
     594                        r = &cpu->rq[j];
     595                        spinlock_lock(&r->lock);
     596                        if (r->n == 0) {
     597                                spinlock_unlock(&r->lock);
     598                                interrupts_restore(ipl);
    611599                                continue;
    612600                        }
    613                        
    614                         thread_t *thread = NULL;
    615                        
    616                         /* Search rq from the back */
    617                         link_t *link = cpu->rq[rq].rq_head.prev;
    618                        
    619                         while (link != &(cpu->rq[rq].rq_head)) {
    620                                 thread = (thread_t *) list_get_instance(link, thread_t, rq_link);
    621                                
     601               
     602                        t = NULL;
     603                        l = r->rq_head.prev;    /* search rq from the back */
     604                        while (l != &r->rq_head) {
     605                                t = list_get_instance(l, thread_t, rq_link);
    622606                                /*
    623607                                 * We don't want to steal CPU-wired threads
     
    627611                                 * steal threads whose FPU context is still in
    628612                                 * CPU.
    629                                  *
    630613                                 */
    631                                 irq_spinlock_lock(&thread->lock, false);
    632                                
    633                                 if ((!(thread->flags & (THREAD_FLAG_WIRED | THREAD_FLAG_STOLEN)))
    634                                     && (!(thread->fpu_context_engaged))) {
     614                                spinlock_lock(&t->lock);
     615                                if ((!(t->flags & (THREAD_FLAG_WIRED |
     616                                    THREAD_FLAG_STOLEN))) &&
     617                                    (!(t->fpu_context_engaged))) {
    635618                                        /*
    636                                          * Remove thread from ready queue.
     619                                         * Remove t from r.
    637620                                         */
    638                                         irq_spinlock_unlock(&thread->lock, false);
     621                                        spinlock_unlock(&t->lock);
    639622                                       
    640623                                        atomic_dec(&cpu->nrdy);
    641624                                        atomic_dec(&nrdy);
    642                                        
    643                                         cpu->rq[rq].n--;
    644                                         list_remove(&thread->rq_link);
    645                                        
     625
     626                                        r->n--;
     627                                        list_remove(&t->rq_link);
     628
    646629                                        break;
    647630                                }
    648                                
    649                                 irq_spinlock_unlock(&thread->lock, false);
    650                                
    651                                 link = link->prev;
    652                                 thread = NULL;
     631                                spinlock_unlock(&t->lock);
     632                                l = l->prev;
     633                                t = NULL;
    653634                        }
    654                        
    655                         if (thread) {
     635                        spinlock_unlock(&r->lock);
     636
     637                        if (t) {
    656638                                /*
    657                                  * Ready thread on local CPU
     639                                 * Ready t on local CPU
    658640                                 */
    659                                
    660                                 irq_spinlock_pass(&(cpu->rq[rq].lock), &thread->lock);
    661                                
     641                                spinlock_lock(&t->lock);
    662642#ifdef KCPULB_VERBOSE
    663643                                printf("kcpulb%u: TID %" PRIu64 " -> cpu%u, "
     
    666646                                    atomic_get(&nrdy) / config.cpu_active);
    667647#endif
    668                                
    669                                 thread->flags |= THREAD_FLAG_STOLEN;
    670                                 thread->state = Entering;
    671                                
    672                                 irq_spinlock_unlock(&thread->lock, true);
    673                                 thread_ready(thread);
    674                                
     648                                t->flags |= THREAD_FLAG_STOLEN;
     649                                t->state = Entering;
     650                                spinlock_unlock(&t->lock);
     651       
     652                                thread_ready(t);
     653
     654                                interrupts_restore(ipl);
     655       
    675656                                if (--count == 0)
    676657                                        goto satisfied;
    677                                
     658                                       
    678659                                /*
    679660                                 * We are not satisfied yet, focus on another
    680661                                 * CPU next time.
    681                                  *
    682662                                 */
    683                                 acpu_bias++;
     663                                k++;
    684664                               
    685665                                continue;
    686                         } else
    687                                 irq_spinlock_unlock(&(cpu->rq[rq].lock), true);
    688                        
    689                 }
    690         }
    691        
     666                        }
     667                        interrupts_restore(ipl);
     668                }
     669        }
     670
    692671        if (atomic_get(&CPU->nrdy)) {
    693672                /*
    694673                 * Be a little bit light-weight and let migrated threads run.
    695                  *
    696674                 */
    697675                scheduler();
     
    700678                 * We failed to migrate a single thread.
    701679                 * Give up this turn.
    702                  *
    703680                 */
    704681                goto loop;
    705682        }
    706        
     683               
    707684        goto not_satisfied;
    708        
     685
    709686satisfied:
    710687        goto loop;
    711688}
     689
    712690#endif /* CONFIG_SMP */
    713691
    714 /** Print information about threads & scheduler queues
    715  *
    716  */
     692
     693/** Print information about threads & scheduler queues */
    717694void sched_print_list(void)
    718695{
    719         size_t cpu;
     696        ipl_t ipl;
     697        unsigned int cpu, i;
     698        runq_t *r;
     699        thread_t *t;
     700        link_t *cur;
     701
     702        /* We are going to mess with scheduler structures,
     703         * let's not be interrupted */
     704        ipl = interrupts_disable();
    720705        for (cpu = 0; cpu < config.cpu_count; cpu++) {
     706
    721707                if (!cpus[cpu].active)
    722708                        continue;
    723                
    724                 irq_spinlock_lock(&cpus[cpu].lock, true);
    725                
    726                 printf("cpu%u: address=%p, nrdy=%" PRIua ", needs_relink=%zu\n",
     709
     710                spinlock_lock(&cpus[cpu].lock);
     711                printf("cpu%u: address=%p, nrdy=%ld, needs_relink=%" PRIs "\n",
    727712                    cpus[cpu].id, &cpus[cpu], atomic_get(&cpus[cpu].nrdy),
    728713                    cpus[cpu].needs_relink);
    729714               
    730                 unsigned int i;
    731715                for (i = 0; i < RQ_COUNT; i++) {
    732                         irq_spinlock_lock(&(cpus[cpu].rq[i].lock), false);
    733                         if (cpus[cpu].rq[i].n == 0) {
    734                                 irq_spinlock_unlock(&(cpus[cpu].rq[i].lock), false);
     716                        r = &cpus[cpu].rq[i];
     717                        spinlock_lock(&r->lock);
     718                        if (!r->n) {
     719                                spinlock_unlock(&r->lock);
    735720                                continue;
    736721                        }
    737                        
    738722                        printf("\trq[%u]: ", i);
    739                         link_t *cur;
    740                         for (cur = cpus[cpu].rq[i].rq_head.next;
    741                             cur != &(cpus[cpu].rq[i].rq_head);
    742                             cur = cur->next) {
    743                                 thread_t *thread = list_get_instance(cur, thread_t, rq_link);
    744                                 printf("%" PRIu64 "(%s) ", thread->tid,
    745                                     thread_states[thread->state]);
     723                        for (cur = r->rq_head.next; cur != &r->rq_head;
     724                                cur = cur->next) {
     725                                t = list_get_instance(cur, thread_t, rq_link);
     726                                printf("%" PRIu64 "(%s) ", t->tid,
     727                                    thread_states[t->state]);
    746728                        }
    747729                        printf("\n");
    748                        
    749                         irq_spinlock_unlock(&(cpus[cpu].rq[i].lock), false);
    750                 }
    751                
    752                 irq_spinlock_unlock(&cpus[cpu].lock, true);
    753         }
     730                        spinlock_unlock(&r->lock);
     731                }
     732                spinlock_unlock(&cpus[cpu].lock);
     733        }
     734       
     735        interrupts_restore(ipl);
    754736}
    755737
Note: See TracChangeset for help on using the changeset viewer.