maxcpus

当uboot 通过bootargs传给给kernel的参数包含maxcpus=n时,就是想动态改变cpu 的个数,由于我们可以停在uboot shell 通过修改maxcpus,就可以动态控制当前kernel smp中cpu的个数。
当uboot 中传给maxcpus=3是,kernel在如下的函数中接收这个字符串并将3存到setup_max_cpus这个变量中


http://lxr.free-electrons.com/source/kernel/smp.c
539 static int __init maxcpus(char *str)
540 {
541         get_option(&str, &setup_max_cpus);
542         if (setup_max_cpus == 0)
543                 arch_disable_smp_support();
544 
545         return 0;
546 }
547 
548 early_param("maxcpus", maxcpus);


而setup_max_cpus 默认是NR_CPUS,这个值是在kernel的defconfig文件中定义的
350 static const unsigned int setup_max_cpus = NR_CPUS;


当从start_kernel中调用smp_prepare_cpus 时会根据max_cpus 来设定cpu_present_mask,最终影响boot的cpu。
如下函数最终smp_prepare_cpus
437 void __init smp_prepare_cpus(unsigned int max_cpus)
438 {
439         unsigned int ncores = num_possible_cpus();
440 
441         init_cpu_topology();
442 
443         smp_store_cpu_info(smp_processor_id());
444 
445         /*
446          * are we trying to boot more cores than exist?
447          */
448         if (max_cpus > ncores)
449                 max_cpus = ncores;
450         if (ncores > 1 && max_cpus) {
451                 /*
452                  * Initialise the present map, which describes the set of CPUs
453                  * actually populated at the present time. A platform should
454                  * re-initialize the map in the platforms smp_prepare_cpus()
455                  * if present != possible (e.g. physical hotplug).
456                  */
457                 init_cpu_present(cpu_possible_mask);
458 
459                 /*
460                  * Initialise the SCU if there are more than one CPU
461                  * and let them know where to start.
462                  */
463                 if (smp_ops.smp_prepare_cpus)
464                         smp_ops.smp_prepare_cpus(max_cpus);
465         }
466 }


smp_prepare_cpus 这个函数是和IC相关的实现,我们以下面的为例
http://lxr.free-electrons.com/source/arch/arc/kernel/smp.c#L65
  65 void __init smp_prepare_cpus(unsigned int max_cpus)
 66 {
 67         int i;
 68 
 69         /*
 70          * Initialise the present map, which describes the set of CPUs
 71          * actually populated at the present time.
 72          */
 73         for (i = 0; i < max_cpus; i++)
 74                 set_cpu_present(i, true);
 75 }


这个函数根据max_cpus来说设定好cpu_present_mask。
这样当我们在从start_kernel中调用smp_init 来boot其他cpu的时候,就会根据这个数来决定要唤醒几个cpu.
566 void __init smp_init(void)
567 {
568         unsigned int cpu;
569 
570         idle_threads_init();
571         cpuhp_threads_init();
572 
573         /* FIXME: This should be done in userspace --RR */
574         for_each_present_cpu(cpu) {
575                 if (num_online_cpus() >= setup_max_cpus)
576                         break;
577                 if (!cpu_online(cpu))
578                         cpu_up(cpu);
579         }
580 
581         /* Any cleanup work */
582         smp_announce();
583         smp_cpus_done(setup_max_cpus);
584 }


关键是574 行的#define for_each_present_cpu(cpu)  for_each_cpu((cpu), cpu_present_mask)
可见主要是cpu 是否在cpu_present_mask中如果在的话,就调用cpu_up来boot cpu。而cpu_present_mask又是被uboot 传递的maxcpus影响的.



你可能感兴趣的:(Linux,源码分析)