lk中的smp

在lk阶段可以实现smp。即将其他cpu都wakeup起来,每个cpu上都可运行,也可是实现调动,这是真正的并行编程.
从start.s开始cpu0 和 其他cpu走的不同的flow。smp相关的code都用WITH_SMP 抱起来了
    /* stay in supervisor and call into arm arch code to continue setup */
    mov     r0, r5
    bl      arm_secondary_entry
如果不是cpu0 就调动arm_secondary_entry
#if WITH_SMP
void arm_secondary_entry(uint asm_cpu_num)
{
    uint cpu = arch_curr_cpu_num();
    if (cpu != asm_cpu_num)
        return;


     lk_secondary_cpu_entry();
}
继续看lk_secondary_cpu_entry的实现
void lk_secondary_cpu_entry(void)
{
    uint cpu = arch_curr_cpu_num();


    if (cpu > secondary_bootstrap_thread_count) {
        dprintf(CRITICAL, "Invalid secondary cpu num %d, SMP_MAX_CPUS %d, secondary_bootstrap_thread_count %d\n",
                cpu, SMP_MAX_CPUS, secondary_bootstrap_thread_count);
        return;
    }


    thread_secondary_cpu_init_early();
    thread_resume(secondary_bootstrap_threads[cpu - 1]);


    dprintf(SPEW, "entering scheduler on cpu %d\n", cpu);
    thread_secondary_cpu_entry();
}


最重要的函数式thread_secondary_cpu_entry
void thread_secondary_cpu_entry(void)
{
    uint cpu = arch_curr_cpu_num();
    thread_t *t = get_current_thread();
    t->priority = IDLE_PRIORITY;


    mp_set_curr_cpu_active(true);
    mp_set_cpu_idle(cpu);


    /* enable interrupts and start the scheduler on this cpu */
    arch_enable_ints();
    thread_yield();


    idle_thread_routine();
}


调用idle_thread_routine 进入dile
static void idle_thread_routine(void)
{
    for (;;)
        arch_idle();
}


在进入idle之前会通过thread_yield()来在这颗cpu上进行调动
上述flow除cpu0 外每个cpu都会跑一边
thread_resched -> get_top_thread 在get_top_thread会分配一个新的thread运行
static thread_t *get_top_thread(int cpu)
{
    thread_t *newthread;
    uint32_t local_run_queue_bitmap = run_queue_bitmap;


    while (local_run_queue_bitmap) {
        /* find the first (remaining) queue with a thread in it */
        uint next_queue = sizeof(run_queue_bitmap) * 8 - 1 - __builtin_clz(local_run_queue_bitmap);


        list_for_every_entry(&run_queue[next_queue], newthread, thread_t, queue_node) {
#if WITH_SMP
            if (newthread->pinned_cpu < 0 || newthread->pinned_cpu == cpu)
#endif
            {
                list_delete(&newthread->queue_node);


                if (list_is_empty(&run_queue[next_queue]))
                    run_queue_bitmap &= ~(1<<next_queue);


                return newthread;
            }
        }


        local_run_queue_bitmap &= ~(1<<next_queue);
    }
    /* no threads to run, select the idle thread for this cpu */
    return idle_thread(cpu);
}


在这个函数中可以看到run_queue 只有一个,并没有每个cpu分配一个run_queue。因此thread是可以在不同cpu上切换运行的,例如通过一个thread上一次在cpu0上运行,下一次可能在cpu1上运行.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值