如何在cpufreq.c文件中扩展“for_each_possible_cpu”?

我正在浏览driver / cpufreq / cpufreq.c以了解它是如何工作的.我遇到了一段我无法理解的代码.

在cpufreq_core_init中:

for_each_possible_cpu(cpu) {
        per_cpu(cpufreq_policy_cpu, cpu) = -1;
        init_rwsem(&per_cpu(cpu_policy_rwsem, cpu));
}

当我浏览定义的宏时,

#define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask)

#define per_cpu(var, cpu) \
        (*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))

#define init_rwsem(sem)                                         \
do {                                                            \
        static struct lock_class_key __key;                     \
                                                                \
        __init_rwsem((sem), #sem, &__key);                      \
} while (0)

我的问题:

> for_each_possible_cpu如何扩展?
>为什么另外两个#defines被调用?
>为什么per_cpu输出等于-1?

最佳答案
  1. How does it expand:

请记住,无论什么时候你问这样的Linux内核,答案都不容易……所以……我们走了:

#define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask)

您可以看到这个宏实际上只是一个for循环,使用迭代器作为cpu调用for_each_cpu是另一个宏,它是定义为的循环部分:

#define for_each_cpu(cpu, mask)                 \
     for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask)

而cpu_possible_mask是一个指向结构的指针:

extern const struct cpumask *const cpu_possible_mask;

这里看到的(由另一个宏组成):

typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;

它包含另一个宏(DECLARE_BITMAP),它有另一个#define用于NR_CPUS,即系统中的CPU数量,它应该是系统相关的并且在kconfig中设置.那里的宏实际上只是一个数组和一个存取器:

#define DECLARE_BITMAP(name,bits) \
      unsigned long name[BITS_TO_LONGS(bits)]

所以你可以看到数组和访问器当然包含另一个#define:

#define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))

…由另外两个#defines组成:

#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#define BITS_PER_BYTE 8

无论如何…你可以看到(A)这是一团糟,(B)它最终成为一个for循环,增加了CPU的数量,但也通过逗号运算符发出第二个迭代动作.第二个运算符自己说出来的确切程度取决于系统. (系统上的长度是多少?系统上的cpu数量是多少?)

2.Why are two others #defines are called inside?

这是#1的回答.由于它扩展为for循环,因此您需要该循环来执行某些操作.

3.Why is the per_cpu output equated to -1?

per_cpu宏给出一个指向系统中每个CPU的CPU频率策略的指针,该策略被初始化为-1.我必须做更多的研究才能确定,但​​可能是因为定义他们选择了:

#define CPUFREQ_ETERNAL                 (-1)

__init_rwsem是一种体系结构定义的方法,用于初始化用于每个CPU策略的读/写信号量.

我不知道这个解释是否有多大帮助,但至少可能有助于指出你更好的方向.好运,探索内核.

转载注明原文:如何在cpufreq.c文件中扩展“for_each_possible_cpu”? - 代码日志