I was browsing through driver/cpufreq/cpufreq.c to understand how it works. I came across this piece of code which I could not understand.
In cpufreq_core_init
:
for_each_possible_cpu(cpu) {
per_cpu(cpufreq_policy_cpu, cpu) = -1;
init_rwsem(&per_cpu(cpu_policy_rwsem, cpu));
}
When I looked through the defined macro,
#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)
My questions:
for_each_possible_cpu
expand?#defines
are called inside?per_cpu
output equated to -1?
- How does it expand:
Keep in mind anytime you ask something like that wrt the Linux kernel, the answer is never easy... so... here we go:
#define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask)
You can see that this macro is really just a for loop, called with an iterator as cpu
the for_each_cpu
is another macro which is the looping part defined as:
#define for_each_cpu(cpu, mask) \
for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask)
And the cpu_possible_mask is a pointer to a struct:
extern const struct cpumask *const cpu_possible_mask;
Which is seen here (consisting of another macro):
typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
That contains another macro (DECLARE_BITMAP
) and it has another #define
for NR_CPUS
, that is the number of CPUs in the system, it should be system dependent and set in the kconfig. The macro in there is really just an array and an accessor:
#define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
So you can see that's the array and the accessor which of course consists of another #define
:
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
...which consists of two more #define
s:
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#define BITS_PER_BYTE 8
Anyway... you can see that (A) this is a mess and (B) it ends up being a for
loop that increments number of CPUs but also issues a second iterative action via the comma operator. How exactly the second operator words itself out is system dependent. (what's the sizeof a long on your system? what's the number of cpus on your system?)
2.Why are two others #defines are called inside?
That's kind of answered by #1. Since it expands to a for
loop, you need that loop to do something.
3.Why is the per_cpu output equated to -1?
The per_cpu
macro is giving a pointer to the CPU frequency policy of each CPU in the system, that is being initialized to -1
. I'd have to do more research to be sure, but presumably they picked that because of the define:
#define CPUFREQ_ETERNAL (-1)
And the __init_rwsem
is an architecture defined way of initializing the read/write semaphore used for each CPU's policy.
I don't know if that explanation helped much, but at least maybe it helps point you in a better direction. Good luck exploring the kernel.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With