Changeset 04803bf in mainline for kernel/generic/src/proc/scheduler.c


Ignore:
Timestamp:
2011-03-21T22:00:17Z (15 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
143932e3
Parents:
b50b5af2 (diff), 7308e84 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes (needs fixes).

File:
1 edited

Legend:

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

    rb50b5af2 r04803bf  
    11/*
    2  * Copyright (c) 2001-2007 Jakub Jermar
     2 * Copyright (c) 2010 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 
    65 static void before_task_runs(void);
    66 static void before_thread_runs(void);
    67 static void after_thread_ran(void);
     64#include <stacktrace.h>
     65
    6866static void scheduler_separated_stack(void);
    6967
    70 atomic_t nrdy;  /**< Number of ready threads in the system. */
     68atomic_t nrdy;  /**< Number of ready threads in the system. */
    7169
    7270/** Carry out actions before new task runs. */
    73 void before_task_runs(void)
     71static void before_task_runs(void)
    7472{
    7573        before_task_runs_arch();
     
    8078 * Perform actions that need to be
    8179 * taken before the newly selected
    82  * tread is passed control.
     80 * thread is passed control.
    8381 *
    8482 * THREAD->lock is locked on entry
    8583 *
    8684 */
    87 void before_thread_runs(void)
     85static void before_thread_runs(void)
    8886{
    8987        before_thread_runs_arch();
     88       
    9089#ifdef CONFIG_FPU_LAZY
    91         if(THREAD == CPU->fpu_owner)
     90        if (THREAD == CPU->fpu_owner)
    9291                fpu_enable();
    9392        else
    94                 fpu_disable(); 
     93                fpu_disable();
    9594#else
    9695        fpu_enable();
     
    102101        }
    103102#endif
     103       
     104#ifdef CONFIG_UDEBUG
     105        if (THREAD->btrace) {
     106                istate_t *istate = THREAD->udebug.uspace_state;
     107                if (istate != NULL) {
     108                        printf("Thread %" PRIu64 " stack trace:\n", THREAD->tid);
     109                        stack_trace_istate(istate);
     110                }
     111               
     112                THREAD->btrace = false;
     113        }
     114#endif
    104115}
    105116
     
    113124 *
    114125 */
    115 void after_thread_ran(void)
     126static void after_thread_ran(void)
    116127{
    117128        after_thread_ran_arch();
     
    123134restart:
    124135        fpu_enable();
    125         spinlock_lock(&CPU->lock);
    126 
     136        irq_spinlock_lock(&CPU->lock, false);
     137       
    127138        /* Save old context */
    128         if (CPU->fpu_owner != NULL) { 
    129                 spinlock_lock(&CPU->fpu_owner->lock);
     139        if (CPU->fpu_owner != NULL) {
     140                irq_spinlock_lock(&CPU->fpu_owner->lock, false);
    130141                fpu_context_save(CPU->fpu_owner->saved_fpu_context);
    131                 /* don't prevent migration */
     142               
     143                /* Don't prevent migration */
    132144                CPU->fpu_owner->fpu_context_engaged = 0;
    133                 spinlock_unlock(&CPU->fpu_owner->lock);
     145                irq_spinlock_unlock(&CPU->fpu_owner->lock, false);
    134146                CPU->fpu_owner = NULL;
    135147        }
    136 
    137         spinlock_lock(&THREAD->lock);
     148       
     149        irq_spinlock_lock(&THREAD->lock, false);
    138150        if (THREAD->fpu_context_exists) {
    139151                fpu_context_restore(THREAD->saved_fpu_context);
     
    142154                if (!THREAD->saved_fpu_context) {
    143155                        /* Might sleep */
    144                         spinlock_unlock(&THREAD->lock);
    145                         spinlock_unlock(&CPU->lock);
     156                        irq_spinlock_unlock(&THREAD->lock, false);
     157                        irq_spinlock_unlock(&CPU->lock, false);
    146158                        THREAD->saved_fpu_context =
    147159                            (fpu_context_t *) slab_alloc(fpu_context_slab, 0);
     160                       
    148161                        /* We may have switched CPUs during slab_alloc */
    149                         goto restart; 
     162                        goto restart;
    150163                }
    151164                fpu_init();
    152165                THREAD->fpu_context_exists = 1;
    153166        }
     167       
    154168        CPU->fpu_owner = THREAD;
    155169        THREAD->fpu_context_engaged = 1;
    156         spinlock_unlock(&THREAD->lock);
    157 
    158         spinlock_unlock(&CPU->lock);
    159 }
    160 #endif
     170        irq_spinlock_unlock(&THREAD->lock, false);
     171       
     172        irq_spinlock_unlock(&CPU->lock, false);
     173}
     174#endif /* CONFIG_FPU_LAZY */
    161175
    162176/** Initialize scheduler
     
    180194static thread_t *find_best_thread(void)
    181195{
    182         thread_t *t;
    183         runq_t *r;
    184         int i;
    185 
    186196        ASSERT(CPU != NULL);
    187 
     197       
    188198loop:
    189         interrupts_enable();
    190199       
    191200        if (atomic_get(&CPU->nrdy) == 0) {
     
    195204                 * This improves energy saving and hyperthreading.
    196205                 */
    197 
     206                irq_spinlock_lock(&CPU->lock, false);
     207                CPU->idle = true;
     208                irq_spinlock_unlock(&CPU->lock, false);
     209                interrupts_enable();
     210               
    198211                /*
    199212                 * An interrupt might occur right now and wake up a thread.
     
    201214                 * even though there is a runnable thread.
    202215                 */
    203 
    204                  cpu_sleep();
    205                  goto loop;
    206         }
    207 
    208         interrupts_disable();
    209        
     216                cpu_sleep();
     217                interrupts_disable();
     218                goto loop;
     219        }
     220       
     221        unsigned int i;
    210222        for (i = 0; i < RQ_COUNT; i++) {
    211                 r = &CPU->rq[i];
    212                 spinlock_lock(&r->lock);
    213                 if (r->n == 0) {
     223                irq_spinlock_lock(&(CPU->rq[i].lock), false);
     224                if (CPU->rq[i].n == 0) {
    214225                        /*
    215226                         * If this queue is empty, try a lower-priority queue.
    216227                         */
    217                         spinlock_unlock(&r->lock);
     228                        irq_spinlock_unlock(&(CPU->rq[i].lock), false);
    218229                        continue;
    219230                }
    220 
     231               
    221232                atomic_dec(&CPU->nrdy);
    222233                atomic_dec(&nrdy);
    223                 r->n--;
    224 
     234                CPU->rq[i].n--;
     235               
    225236                /*
    226237                 * Take the first thread from the queue.
    227238                 */
    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 
     239                thread_t *thread =
     240                    list_get_instance(CPU->rq[i].rq_head.next, thread_t, rq_link);
     241                list_remove(&thread->rq_link);
     242               
     243                irq_spinlock_pass(&(CPU->rq[i].lock), &thread->lock);
     244               
     245                thread->cpu = CPU;
     246                thread->ticks = us2ticks((i + 1) * 10000);
     247                thread->priority = i;  /* Correct rq index */
     248               
    239249                /*
    240250                 * Clear the THREAD_FLAG_STOLEN flag so that t can be migrated
    241251                 * when load balancing needs emerge.
    242252                 */
    243                 t->flags &= ~THREAD_FLAG_STOLEN;
    244                 spinlock_unlock(&t->lock);
    245 
    246                 return t;
    247         }
     253                thread->flags &= ~THREAD_FLAG_STOLEN;
     254                irq_spinlock_unlock(&thread->lock, false);
     255               
     256                return thread;
     257        }
     258       
    248259        goto loop;
    249 
    250260}
    251261
     
    264274{
    265275        link_t head;
    266         runq_t *r;
    267         int i, n;
    268 
     276       
    269277        list_initialize(&head);
    270         spinlock_lock(&CPU->lock);
     278        irq_spinlock_lock(&CPU->lock, false);
     279       
    271280        if (CPU->needs_relink > NEEDS_RELINK_MAX) {
     281                int i;
    272282                for (i = start; i < RQ_COUNT - 1; i++) {
    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);
    280                
    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                 }
     283                        /* Remember and empty rq[i + 1] */
     284                       
     285                        irq_spinlock_lock(&CPU->rq[i + 1].lock, false);
     286                        list_concat(&head, &CPU->rq[i + 1].rq_head);
     287                        size_t n = CPU->rq[i + 1].n;
     288                        CPU->rq[i + 1].n = 0;
     289                        irq_spinlock_unlock(&CPU->rq[i + 1].lock, false);
     290                       
     291                        /* Append rq[i + 1] to rq[i] */
     292                       
     293                        irq_spinlock_lock(&CPU->rq[i].lock, false);
     294                        list_concat(&CPU->rq[i].rq_head, &head);
     295                        CPU->rq[i].n += n;
     296                        irq_spinlock_unlock(&CPU->rq[i].lock, false);
     297                }
     298               
    288299                CPU->needs_relink = 0;
    289300        }
    290         spinlock_unlock(&CPU->lock);
    291 
     301       
     302        irq_spinlock_unlock(&CPU->lock, false);
    292303}
    293304
     
    302313{
    303314        volatile ipl_t ipl;
    304 
     315       
    305316        ASSERT(CPU != NULL);
    306 
     317       
    307318        ipl = interrupts_disable();
    308 
     319       
    309320        if (atomic_get(&haltstate))
    310321                halt();
    311322       
    312323        if (THREAD) {
    313                 spinlock_lock(&THREAD->lock);
    314                
    315                 /* Update thread accounting */
    316                 THREAD->cycles += get_cycle() - THREAD->last_cycle;
     324                irq_spinlock_lock(&THREAD->lock, false);
     325               
     326                /* Update thread kernel accounting */
     327                THREAD->kcycles += get_cycle() - THREAD->last_cycle;
    317328               
    318329#ifndef CONFIG_FPU_LAZY
     
    327338                        THREAD->last_cycle = get_cycle();
    328339                       
    329                         spinlock_unlock(&THREAD->lock);
     340                        irq_spinlock_unlock(&THREAD->lock, false);
    330341                        interrupts_restore(THREAD->saved_context.ipl);
    331342                       
    332343                        return;
    333344                }
    334 
     345               
    335346                /*
    336347                 * Interrupt priority level of preempted thread is recorded
    337348                 * here to facilitate scheduler() invocations from
    338                  * interrupts_disable()'d code (e.g. waitq_sleep_timeout()).
     349                 * interrupts_disable()'d code (e.g. waitq_sleep_timeout()).
     350                 *
    339351                 */
    340352                THREAD->saved_context.ipl = ipl;
    341353        }
    342 
     354       
    343355        /*
    344356         * Through the 'THE' structure, we keep track of THREAD, TASK, CPU, VM
    345357         * and preemption counter. At this point THE could be coming either
    346358         * from THREAD's or CPU's stack.
     359         *
    347360         */
    348361        the_copy(THE, (the_t *) CPU->stack);
    349 
     362       
    350363        /*
    351364         * We may not keep the old stack.
     
    359372         * Therefore the scheduler() function continues in
    360373         * scheduler_separated_stack().
     374         *
    361375         */
    362376        context_save(&CPU->saved_context);
     
    364378            (uintptr_t) CPU->stack, CPU_STACK_SIZE);
    365379        context_restore(&CPU->saved_context);
    366         /* not reached */
     380       
     381        /* Not reached */
    367382}
    368383
     
    373388 * switch to a new thread.
    374389 *
    375  * Assume THREAD->lock is held.
    376390 */
    377391void scheduler_separated_stack(void)
    378392{
    379         int priority;
    380393        DEADLOCK_PROBE_INIT(p_joinwq);
    381 
     394        task_t *old_task = TASK;
     395        as_t *old_as = AS;
     396       
     397        ASSERT((!THREAD) || (irq_spinlock_locked(&THREAD->lock)));
    382398        ASSERT(CPU != NULL);
    383399       
     400        /*
     401         * Hold the current task and the address space to prevent their
     402         * possible destruction should thread_destroy() be called on this or any
     403         * other processor while the scheduler is still using them.
     404         */
     405        if (old_task)
     406                task_hold(old_task);
     407       
     408        if (old_as)
     409                as_hold(old_as);
     410       
    384411        if (THREAD) {
    385                 /* must be run after the switch to scheduler stack */
     412                /* Must be run after the switch to scheduler stack */
    386413                after_thread_ran();
    387 
     414               
    388415                switch (THREAD->state) {
    389416                case Running:
    390                         spinlock_unlock(&THREAD->lock);
     417                        irq_spinlock_unlock(&THREAD->lock, false);
    391418                        thread_ready(THREAD);
    392419                        break;
    393 
     420               
    394421                case Exiting:
    395422repeat:
    396423                        if (THREAD->detached) {
    397                                 thread_destroy(THREAD);
     424                                thread_destroy(THREAD, false);
    398425                        } else {
    399426                                /*
     
    401428                                 * somebody calls thread_detach() on it.
    402429                                 */
    403                                 if (!spinlock_trylock(&THREAD->join_wq.lock)) {
     430                                if (!irq_spinlock_trylock(&THREAD->join_wq.lock)) {
    404431                                        /*
    405432                                         * Avoid deadlock.
    406433                                         */
    407                                         spinlock_unlock(&THREAD->lock);
     434                                        irq_spinlock_unlock(&THREAD->lock, false);
    408435                                        delay(HZ);
    409                                         spinlock_lock(&THREAD->lock);
     436                                        irq_spinlock_lock(&THREAD->lock, false);
    410437                                        DEADLOCK_PROBE(p_joinwq,
    411438                                            DEADLOCK_THRESHOLD);
     
    414441                                _waitq_wakeup_unsafe(&THREAD->join_wq,
    415442                                    WAKEUP_FIRST);
    416                                 spinlock_unlock(&THREAD->join_wq.lock);
     443                                irq_spinlock_unlock(&THREAD->join_wq.lock, false);
    417444                               
    418445                                THREAD->state = Lingering;
    419                                 spinlock_unlock(&THREAD->lock);
     446                                irq_spinlock_unlock(&THREAD->lock, false);
    420447                        }
    421448                        break;
     
    426453                         */
    427454                        THREAD->priority = -1;
    428 
     455                       
    429456                        /*
    430457                         * We need to release wq->lock which we locked in
     
    432459                         * THREAD->sleep_queue.
    433460                         */
    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 
     461                        irq_spinlock_unlock(&THREAD->sleep_queue->lock, false);
     462                       
     463                        irq_spinlock_unlock(&THREAD->lock, false);
    448464                        break;
    449 
     465               
    450466                default:
    451467                        /*
     
    456472                        break;
    457473                }
    458 
     474               
    459475                THREAD = NULL;
    460476        }
    461 
     477       
    462478        THREAD = find_best_thread();
    463479       
    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.
     480        irq_spinlock_lock(&THREAD->lock, false);
     481        int priority = THREAD->priority;
     482        irq_spinlock_unlock(&THREAD->lock, false);
     483       
     484        relink_rq(priority);
     485       
     486        /*
     487         * If both the old and the new task are the same,
     488         * lots of work is avoided.
    473489         */
    474490        if (TASK != THREAD->task) {
    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);
     491                as_t *new_as = THREAD->task->as;
    487492               
    488493                /*
    489                  * Note that it is possible for two tasks to share one address
    490                  * space.
     494                 * Note that it is possible for two tasks
     495                 * to share one address space.
    491496                 */
    492                 if (as1 != as2) {
     497                if (old_as != new_as) {
    493498                        /*
    494499                         * Both tasks and address spaces are different.
    495500                         * Replace the old one with the new one.
    496501                         */
    497                         as_switch(as1, as2);
    498                 }
     502                        as_switch(old_as, new_as);
     503                }
     504               
    499505                TASK = THREAD->task;
    500506                before_task_runs();
    501507        }
    502 
    503         spinlock_lock(&THREAD->lock);   
     508       
     509        if (old_task)
     510                task_release(old_task);
     511       
     512        if (old_as)
     513                as_release(old_as);
     514       
     515        irq_spinlock_lock(&THREAD->lock, false);
    504516        THREAD->state = Running;
    505 
     517       
    506518#ifdef SCHEDULER_VERBOSE
    507519        printf("cpu%u: tid %" PRIu64 " (priority=%d, ticks=%" PRIu64
    508520            ", nrdy=%ld)\n", CPU->id, THREAD->tid, THREAD->priority,
    509521            THREAD->ticks, atomic_get(&CPU->nrdy));
    510 #endif 
    511 
     522#endif
     523       
    512524        /*
    513525         * Some architectures provide late kernel PA2KA(identity)
     
    519531         */
    520532        before_thread_runs();
    521 
     533       
    522534        /*
    523535         * Copy the knowledge of CPU, TASK, THREAD and preemption counter to
     
    527539       
    528540        context_restore(&THREAD->saved_context);
    529         /* not reached */
     541       
     542        /* Not reached */
    530543}
    531544
     
    541554void kcpulb(void *arg)
    542555{
    543         thread_t *t;
    544         int count, average, j, k = 0;
    545         unsigned int i;
    546         ipl_t ipl;
    547 
     556        atomic_count_t average;
     557        atomic_count_t rdy;
     558       
    548559        /*
    549560         * Detach kcpulb as nobody will call thread_join_timeout() on it.
     
    556567         */
    557568        thread_sleep(1);
    558 
     569       
    559570not_satisfied:
    560571        /*
     
    562573         * other CPU's. Note that situation can have changed between two
    563574         * passes. Each time get the most up to date counts.
     575         *
    564576         */
    565577        average = atomic_get(&nrdy) / config.cpu_active + 1;
    566         count = average - atomic_get(&CPU->nrdy);
    567 
    568         if (count <= 0)
     578        rdy = atomic_get(&CPU->nrdy);
     579       
     580        if (average <= rdy)
    569581                goto satisfied;
    570 
     582       
     583        atomic_count_t count = average - rdy;
     584       
    571585        /*
    572586         * Searching least priority queues on all CPU's first and most priority
    573587         * queues on all CPU's last.
    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 
     588         *
     589         */
     590        size_t acpu;
     591        size_t acpu_bias = 0;
     592        int rq;
     593       
     594        for (rq = RQ_COUNT - 1; rq >= 0; rq--) {
     595                for (acpu = 0; acpu < config.cpu_active; acpu++) {
     596                        cpu_t *cpu = &cpus[(acpu + acpu_bias) % config.cpu_active];
     597                       
    583598                        /*
    584599                         * Not interested in ourselves.
    585600                         * Doesn't require interrupt disabling for kcpulb has
    586601                         * THREAD_FLAG_WIRED.
     602                         *
    587603                         */
    588604                        if (CPU == cpu)
    589605                                continue;
     606                       
    590607                        if (atomic_get(&cpu->nrdy) <= average)
    591608                                continue;
    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);
     609                       
     610                        irq_spinlock_lock(&(cpu->rq[rq].lock), true);
     611                        if (cpu->rq[rq].n == 0) {
     612                                irq_spinlock_unlock(&(cpu->rq[rq].lock), true);
    599613                                continue;
    600614                        }
    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);
     615                       
     616                        thread_t *thread = NULL;
     617                       
     618                        /* Search rq from the back */
     619                        link_t *link = cpu->rq[rq].rq_head.prev;
     620                       
     621                        while (link != &(cpu->rq[rq].rq_head)) {
     622                                thread = (thread_t *) list_get_instance(link, thread_t, rq_link);
     623                               
    606624                                /*
    607625                                 * We don't want to steal CPU-wired threads
     
    611629                                 * steal threads whose FPU context is still in
    612630                                 * CPU.
     631                                 *
    613632                                 */
    614                                 spinlock_lock(&t->lock);
    615                                 if ((!(t->flags & (THREAD_FLAG_WIRED |
    616                                     THREAD_FLAG_STOLEN))) &&
    617                                     (!(t->fpu_context_engaged))) {
     633                                irq_spinlock_lock(&thread->lock, false);
     634                               
     635                                if ((!(thread->flags & (THREAD_FLAG_WIRED | THREAD_FLAG_STOLEN)))
     636                                    && (!(thread->fpu_context_engaged))) {
    618637                                        /*
    619                                          * Remove t from r.
     638                                         * Remove thread from ready queue.
    620639                                         */
    621                                         spinlock_unlock(&t->lock);
     640                                        irq_spinlock_unlock(&thread->lock, false);
    622641                                       
    623642                                        atomic_dec(&cpu->nrdy);
    624643                                        atomic_dec(&nrdy);
    625 
    626                                         r->n--;
    627                                         list_remove(&t->rq_link);
    628 
     644                                       
     645                                        cpu->rq[rq].n--;
     646                                        list_remove(&thread->rq_link);
     647                                       
    629648                                        break;
    630649                                }
    631                                 spinlock_unlock(&t->lock);
    632                                 l = l->prev;
    633                                 t = NULL;
     650                               
     651                                irq_spinlock_unlock(&thread->lock, false);
     652                               
     653                                link = link->prev;
     654                                thread = NULL;
    634655                        }
    635                         spinlock_unlock(&r->lock);
    636 
    637                         if (t) {
     656                       
     657                        if (thread) {
    638658                                /*
    639                                  * Ready t on local CPU
     659                                 * Ready thread on local CPU
    640660                                 */
    641                                 spinlock_lock(&t->lock);
     661                               
     662                                irq_spinlock_pass(&(cpu->rq[rq].lock), &thread->lock);
     663                               
    642664#ifdef KCPULB_VERBOSE
    643665                                printf("kcpulb%u: TID %" PRIu64 " -> cpu%u, "
     
    646668                                    atomic_get(&nrdy) / config.cpu_active);
    647669#endif
    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        
     670                               
     671                                thread->flags |= THREAD_FLAG_STOLEN;
     672                                thread->state = Entering;
     673                               
     674                                irq_spinlock_unlock(&thread->lock, true);
     675                                thread_ready(thread);
     676                               
    656677                                if (--count == 0)
    657678                                        goto satisfied;
    658                                        
     679                               
    659680                                /*
    660681                                 * We are not satisfied yet, focus on another
    661682                                 * CPU next time.
     683                                 *
    662684                                 */
    663                                 k++;
     685                                acpu_bias++;
    664686                               
    665687                                continue;
    666                         }
    667                         interrupts_restore(ipl);
    668                 }
    669         }
    670 
     688                        } else
     689                                irq_spinlock_unlock(&(cpu->rq[rq].lock), true);
     690                       
     691                }
     692        }
     693       
    671694        if (atomic_get(&CPU->nrdy)) {
    672695                /*
    673696                 * Be a little bit light-weight and let migrated threads run.
     697                 *
    674698                 */
    675699                scheduler();
     
    678702                 * We failed to migrate a single thread.
    679703                 * Give up this turn.
     704                 *
    680705                 */
    681706                goto loop;
    682707        }
    683                
     708       
    684709        goto not_satisfied;
    685 
     710       
    686711satisfied:
    687712        goto loop;
    688713}
    689 
    690714#endif /* CONFIG_SMP */
    691715
    692 
    693 /** Print information about threads & scheduler queues */
     716/** Print information about threads & scheduler queues
     717 *
     718 */
    694719void sched_print_list(void)
    695720{
    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();
     721        size_t cpu;
    705722        for (cpu = 0; cpu < config.cpu_count; cpu++) {
    706 
    707723                if (!cpus[cpu].active)
    708724                        continue;
    709 
    710                 spinlock_lock(&cpus[cpu].lock);
    711                 printf("cpu%u: address=%p, nrdy=%ld, needs_relink=%" PRIs "\n",
     725               
     726                irq_spinlock_lock(&cpus[cpu].lock, true);
     727               
     728                printf("cpu%u: address=%p, nrdy=%" PRIua ", needs_relink=%zu\n",
    712729                    cpus[cpu].id, &cpus[cpu], atomic_get(&cpus[cpu].nrdy),
    713730                    cpus[cpu].needs_relink);
    714731               
     732                unsigned int i;
    715733                for (i = 0; i < RQ_COUNT; i++) {
    716                         r = &cpus[cpu].rq[i];
    717                         spinlock_lock(&r->lock);
    718                         if (!r->n) {
    719                                 spinlock_unlock(&r->lock);
     734                        irq_spinlock_lock(&(cpus[cpu].rq[i].lock), false);
     735                        if (cpus[cpu].rq[i].n == 0) {
     736                                irq_spinlock_unlock(&(cpus[cpu].rq[i].lock), false);
    720737                                continue;
    721738                        }
     739                       
    722740                        printf("\trq[%u]: ", i);
    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]);
     741                        link_t *cur;
     742                        for (cur = cpus[cpu].rq[i].rq_head.next;
     743                            cur != &(cpus[cpu].rq[i].rq_head);
     744                            cur = cur->next) {
     745                                thread_t *thread = list_get_instance(cur, thread_t, rq_link);
     746                                printf("%" PRIu64 "(%s) ", thread->tid,
     747                                    thread_states[thread->state]);
    728748                        }
    729749                        printf("\n");
    730                         spinlock_unlock(&r->lock);
    731                 }
    732                 spinlock_unlock(&cpus[cpu].lock);
    733         }
    734        
    735         interrupts_restore(ipl);
     750                       
     751                        irq_spinlock_unlock(&(cpus[cpu].rq[i].lock), false);
     752                }
     753               
     754                irq_spinlock_unlock(&cpus[cpu].lock, true);
     755        }
    736756}
    737757
Note: See TracChangeset for help on using the changeset viewer.