Re: [tip: sched/core] sched/topology: Compute sd_weight considering cpuset partitions
From: K Prateek Nayak
Date: Sat Mar 21 2026 - 11:17:25 EST
Hello Shrikanth,
On 3/21/2026 7:43 PM, Shrikanth Hegde wrote:
>> And more evidence - by default we have:
>>
>> sched_domain size: 296
>> offset of sd_span: 292
>>
>> sizeof() seems to account some sort of 4-byte padding for the struct which
>> pushes the offset of sd->span into the struct size.
>>
>> To resolve this, we can also do:
>>
>> diff --git a/include/linux/sched/topology.h b/include/linux/sched/topology.h
>> index a1e1032426dc..48bea2f7f750 100644
>> --- a/include/linux/sched/topology.h
>> +++ b/include/linux/sched/topology.h
>> @@ -148,7 +148,7 @@ struct sched_domain {
>> * by attaching extra space to the end of the structure,
>> * depending on how many CPUs the kernel has booted up with)
>> */
>> - unsigned long span[];
>> + unsigned long span[] __aligned(2 * sizeof(int));
>> };
>
> Wouldn't that be susceptible to change in sched_domain somewhere in between?
> Right now, it maybe aligning to 296 since it is 8 byte aligned.
>
> But lets say someone adds a new int in between. Then size of sched_domain would be 300.
> but span would still be 296 since it 8 bit aligned?
So the official GCC specification for "Arrays of Length Zero" [1] says:
Although the size of a zero-length array is zero, an array member of
this kind may increase the size of the enclosing type as a result of
tail padding.
so you can either have:
struct sched_domain {
...
unsigned int span_length; /* 288 4 */
unsigned long span[]; /* 292 0 */
/* XXX 4 byte tail padding */
/* size: 296 */
}
or:
struct sched_domain {
...
unsigned int span_length; /* 288 4 */
/* XXX 4 bytes hole, try to pack */
unsigned long span[]; /* 296 0 */
/* size: 296 */
}
If the variable length array is aligned, there is no need for a tail
padding and in both cases, length of span[] is always 0.
[1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
But ...
>
>> static inline struct cpumask *sched_domain_span(struct sched_domain *sd)
>> ---
>>
>> and the kernel boots fine with the sd_span offset aligned with
>> sched_domain struct size:
>>
>> sched_domain size: 296
>> offset of sd_span: 296
>>
>>
>> So Peter, which solution do you prefer?
>>
>> 1. Doing cpumask_and() after the *sd = { ... } initialization. (or)
>>
>> 2. Align sd->span to an 8-byte boundary.
>>
>
> Only update sd_weight and leave everything as it was earlier?
>
> sd_weight = cpumask_and_weight(cpu_map, tl->mask(tl, cpu));
... I agree with you and Chenyu, that this approach is better since
padding and alignment is again dependent on the compiler.
Anyhow we do a cpumask_weight() for sd_weight, and cpumask_and_weight()
being the same complexity shouldn't add any more overhead.
While we are at it, we can also remove that "sd->span_weight" assignment
before the build_sched_groups() loop since we already have it here.
--
Thanks and Regards,
Prateek