Linux kernel名物よくわからないけど便利なforeachマクロ(CPU番号編)

Linux kernelと言えばlist_for_eachみたいな謎のマクロでよくわからないがforeachできる事はよく知られているが、他にも色々あるのだなぁと知ったのでメモ。

#define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask)
#define for_each_online_cpu(cpu)   for_each_cpu((cpu), cpu_online_mask)
#define for_each_present_cpu(cpu)  for_each_cpu((cpu), cpu_present_mask)

for_each_possible_cpuはシステムに存在可能なCPU番号をイテレート、for_each_online_cpuはシステムで今オンラインなCPU番号をイテレート、for_each_present_cpuはオフラインも含めて今存在しているCPU番号をイテレート、だと思われる。
実装としてはそれぞれグローバルに定義されたstruct cpumaskをfor_each_cpuへ与えている。

#define for_each_cpu(cpu, mask)                         \
        for ((cpu) = -1;                                \
                (cpu) = cpumask_next((cpu), (mask)),    \
                (cpu) < nr_cpu_ids;)
static inline unsigned int cpumask_next(int n, const struct cpumask *srcp)
{
        /* -1 is a legal arg here. */
        if (n != -1)
                cpumask_check(n);
        return find_next_bit(cpumask_bits(srcp), nr_cpumask_bits, n+1);
}

for_each_cpuはcpumask_nextで実装されており、cpumask_nextはfind_next_bitで実装されている。
CPUごとに構造体をアロケートするpercpuフレームワークと一緒に使われていることが多そう。

ポイントは、定義されたMAXCPUSみたいな変数でfor文を組むとCPU番号が飛び飛びになっているような状態に対応できないが、CPU番号のビットマスクを用意してその辺に対応しているという事だろう。