č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, &params->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


Reply via email to