👻

CPU MASK

2022/10/16に公開

CPU MASK
CPU MASKとはCPUの状態を表すビットマップ配列です。
以下の4種類あり、それぞれが0または1の値を取る。

/include/linux/cpumask.h
cpu_possible_mask : NR_CPUSの値と同じになる。
cpu_present_mask : 現在、どのCPUが接続されているかを示す。
cpu_online_mask : cpu_present のサブセットで、スケジューラからアクセス可能なCPUを示す。
cpu_active_mask : このマスクのいくつかのビットは、タスクが特定のプロセッサに移動した可能性があることをLinuxカーネルに伝えます。

#以下グローバル変数としてアクセスできます。
extern struct cpumask __cpu_possible_mask;
extern struct cpumask __cpu_online_mask;
extern struct cpumask __cpu_present_mask;
extern struct cpumask __cpu_active_mask;

cpu_online_maskで説明します。
CPUを管理する配列です。ここでいうCPUとは物理CPUではなく、論理CPUです。

CPU数が8個の場合、1が2進数で8個並びます。
cpu_mask_online->bits[0] = 2進数で11111111の値になります。

72個の場合、1が2進数で72個並びます。
cpu_online_mask->bits[0]はunsigned long型(64bit)なので、
cpu_online_mask->bits[0]は1が64個並びます。
cpu_online_mask->bits[1]にあふれた1が8個並びます。

CPUの最大数はNR_CPUS = CONFIG_NR_CPUS = 8192なので1が8192個並ぶ可能性があります。
定義の計算式が以下です。

unsigend long cpu_online_mask->bits[NR_CPU *  / sizeof(long)]
unsigned long cpu_online_mask->bits[8192 *    /8]
unsigned long cpu_online_mask->bits[182]となります。

実際に設定するところを見ていきます。
2段階で設定しています。

boot_cpu_initで初期化されます。

/kernel/cpu.c
//Activate the first processor.
void __init boot_cpu_init(void)
{
	int cpu = smp_processor_id();

	/* Mark the boot cpu "present", "online" etc for SMP and UP case */
	set_cpu_online(cpu, true);    
	set_cpu_active(cpu, true);
	set_cpu_present(cpu, true);
	set_cpu_possible(cpu, true);

#ifdef CONFIG_SMP
	__boot_cpu_id = cpu;
#endif
}

4つのCPU MAPですが、先にpossibleとpresentが決まります。
presentの値を受けてonlineが設定されます。

setup_arch
  acpi_boot_init
    acpi_process_madt 
      acpi_parse_madt_lapic_entries
        acpi_table_parse_entries_array
          acpi_parse_entries_array
            acpi_parse_lapic
              acpi_register_lapic
                generic_processor_info

generic_processor_info {
	set_cpu_possible(cpu, true);
	physid_set(apicid, phys_cpu_present_map);
	set_cpu_present(cpu, true);
	num_processors++;
}

/online
Active the first processerとあるように最初の設定です。
smp_processor_id()は起動時0を返すので、cpu = 0です。
set_cpu_online(0, true)を実行します。
この結果, cpu_online_mask->bits[0]は1になります。

1番目以降はstart_secondaryが呼び出している。

smp_init()
  bringup_nonboot_cpus()
    cpu_up()
      _cpu_up()
        cpuhp_up_callbacks()
          cpuhp_invoke_callback_range()
            cpuhp_invoke_callback()
              cpuhp_hp_states[CPUHP_BRINGUP_CPU] 
                bringup_cpu()
                  __cpu_up()
                    native_cpu_up()
                      do_boot_cpu()
                        start_secondary()
                          set_cpu_online()

set_cpu_online(1, true)
set_cpu_online(2, true)
set_cpu_online(3, true)
...
set_cpu_online(71, true)
以降、論理CPUの数だけset_cpu_onlineを設定しています。

https://zhuanlan.zhihu.com/p/163850501

https://www.dingmos.com/index.php/archives/35/

https://vh21.github.io/linux/2015/04/28/linux-cpu-mask.html

https://linux-note.hatenablog.com/search?q=cpumask

https://0xax.gitbooks.io/linux-insides/content/Concepts/linux-cpu-2.html

https://satoru739.hatenadiary.com/entry/20100820/1282274743

https://0xax.gitbooks.io/linux-insides/content/Concepts/linux-cpu-2.html

https://postd.cc/cpumask/

https://www.cnblogs.com/zhangzhiwei122/p/16093602.html

https://zhuanlan.zhihu.com/p/536776611

https://zhuanlan.zhihu.com/p/545550388

https://zhuanlan.zhihu.com/p/536776611

https://zhuanlan.zhihu.com/p/545550388

https://www.cnblogs.com/zhangzhiwei122/p/16093602.html

https://www.cnblogs.com/zhangzhiwei122/p/16093412.html

Discussion