čt 2. 10. 2025 v 14:36 odesílatel Costa Shulyupin
<[email protected]> napsal:
> +#define for_each_monitored_cpu(cpu, nr_cpus, common) \
> + for (cpu = 0; cpu < nr_cpus; cpu++) \
> + if (!(common)->cpus || CPU_ISSET(cpu,
> &(common)->monitored_cpus))
> +
There is one case where this form of macro is not ideal. Consider this code:
if (something)
for_each_monitored_cpu(i, nr_cpus, ¶ms->common) {
do_something()
}
else
something_else();
Here, since the macro includes an "if" statement, it will eat the else
block (see [1]), and something_else() will be executed for all
non-monitored CPUs (which might be zero times, or many times, instead
of just once, as one would expect). This would not happen for the
other for_each_* macros used in the Linux kernel, since they do not
include an if.
This can be fixed by moving the if to a function called from inside
the for loop:
static inline int next_monitored_cpu(int cpu, int nr_cpus, struct
common_params *common)
{
for (cpu += 1; cpu < nr_cpus; cpu++)
if (!common->cpus || CPU_ISSET(cpu, &common->monitored_cpus))
break;
return cpu;
}
and then defining for_each_monitored_cpu() macro like this:
#define for_each_monitored_cpu(cpu, nr_cpus, common) \
for (cpu = 0; cpu < nr_cpus; cpu = next_monitored_cpu(cpu, nr_cpus, common))
Nevertheless, I took the patch already, and it is still better than
repeating the same code multiple times, so this is for a future
improvement.
[1] - https://en.wikipedia.org/wiki/Dangling_else
Tomas