[PATCH] glibc: Remove CPU set size checking from affinity functions [BZ #19143]
Florian Weimer
fweimer@redhat.com
Fri Oct 23 14:00:00 GMT 2015
On 10/19/2015 07:23 PM, Carlos O'Donell wrote:
>> The current situation, briefly stated, is this: glibc tries to guess the
>> kernel CPU set size and rejects attempts to specify an affinity mask
>> which is larger than that, but it does not work, and glibc and the
>> kernel still silently accept CPU affinity masks with invalid bits,
>> without returning an error. The glibc check does not provide any value
>> to applications, it just adds pointless complexity to the library.
>> Therefore, I want to remove it from glibc.
>
> The point of the code you want to remove was to detect the case where
> the user set CPU bits outside of the maximum possible number of supported
> CPUs. AFAIK today that value is CONFIG_NR_CPUS and the various variables
> that derive from that value.
CONFIG_NR_CPUS is the absolute maximum for a specific kernel (available
at run time in /sys/devices/system/cpu/kernel_max). The kernel lowers
the observable value if it detects the system cannot support more than a
specific number of CPUs. This is the kernel-internal nr_cpu_ids
variable. I don't think its value is directly exported, but it can
currently be derived from /sys/devices/system/cpu/possible.
(The difficulty of obtaining this value, and the tendency of the kernel
to replace hard compile-time limits with run-time configuration options,
makes me think it is unwise to expose these values through sysconf.)
> Can you elaborate some more on any of the false negative cases you think
> might impact user applications? For example what happens if you use the
> stock cpu_set_t size? It would seem to me that such a use keeps working
> and there is no change.
Yes, applications which worked before continue to work. But you can now
specify an all-ones mask you have allocated, and glibc will not reject
it because it has set bits beyond the value it guessed for nr_cpu_ids.
>> Remove CPU set size checking from affinity functions [BZ #19143]
>>
>> With current kernel versions, the check does not reliably detect that
>> unavailable CPUs are requested, for these reasons:
>>
>> (1) The kernel will silently ignore non-allowed CPUs.
>
> You mean to say that if sched_setaffinity is called with a CPU mask
> bit set to enabled, but that cpu is not allowed for the process, then
> it will ignore the setting?
Yes, that is what the kernel does.
> This requires you run sched_getaffinity to
> verify what CPUs you're actually set to run on?
Yes, if you care about this detail.
> Is this because the
> cpuset mechanism is merged with sched_setaffinity and overrides it?
As far as I can tell, yes. I do not know where the kernel gets the
other mask from, but it seems cgroups-related (hence the Cc:), and it
does and AND on those two masks.
>> (3) The existing probing code assumes that the CPU mask size is a
>> power of two and at least 1024. Neither it has to be a power
>> of two, nor is the minimum possible value 1024, so the value
>> determined is often too large, resulting in incorrect false
>> negatives.
>
> Could you explain those "false negative" cases again?
I tried to make this clearer in the revised commit message of the
attached patch.
> The goal is to keep nptl/ free from linux-isms, and AFAICT your test is
> indeed free of any linux-specific features since your code for finding
> the size of the cpu mask is generic. Is there anything I might have missed
> that would make your test linux-specific? Keep in mind that we share nptl/
> with the nacl port.
Good point. sched_getcpu is not universally available, so I had to move
the tests to sysdeps/unix/sysv/linux.
I noticed that tst-getcpu was failing (bug 19164), so I added another
sched_setaffinity test variant that supersedes it.
>> +* sched_setaffinity, pthread_setaffinity_np no longer attempt to guess the
>> + kernel-internal CPU set size. This means that requests that change the
>> + CPU affinity which failed before will now succeed. Applications that need
>
> Please provide at least one example of a failure which now succeeds.
I've updated the NEWS entry.
>> +/* We wave two loops running for two seconds each. */
>> +#define TIMEOUT 8
>
> Why two seconds?
>
> Why two threads?
>
> If the value of 2 seconds is arbitrary please state so in
> a comment such that future reviewers can adjust it as they
> see fit without having to review the history of the value.
Should be clearer in the new version.
>> +++ b/posix/tst-affinity.c
>> @@ -0,0 +1,254 @@
>
> Needs a one line test description with BZ#.
I did not include the bug number because it is a generic, non-regression
test.
>> +static int
>> +find_set_size (void)
>> +{
>> + /* We need to use multiples of 64 because otherwise, CPU_ALLOC
>> + over-allocates, and and we do not see all bits returned by the
>> + kernel. */
>
> How does CPU_ALLOC over-allocating result in not seeing bits from
> the kernel? Is this because you get over-allocation in CPU_ALLOC,
> but your own external count of num_cpus would be lower and it's
> num_cpus you return? Can't you rely on the result of CPU_ALLOC_SIZE
> and return that?
See find_last_cpu. It is tricky to determine the actual size of a CPU
set just based on the macros. I think I got it right.
It turns out the comment was incorrect, I changed the code.
> Why do we do this instead of calling sysconf to get the number
> of CPUs?
sysconf currently does not give us the proper number, and I really don't
think applications should rely on it. This is a separate conversation,
IMHO. I added a comment.
>> +
>> +static bool
>> +test_size (const struct conf *conf, size_t size)
>> +{
>
> Should print PASS:/FAIL: prefix to make grepping easier.
I added info/warning/error prefixes instead.
> Should do what other tests do e.g. err |= and run each
> test on a distinct line. Makes it easier to add tests and
> disable tests while debugging.
Ah, right.
I have added tests which cover additional scenarios (cross-process
sched_* calls and cross-thread pthread_sched* calls).
Florian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Remove-CPU-set-size-checking-from-affinity-functions.patch
Type: text/x-patch
Size: 44624 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-alpha/attachments/20151023/3ee9f775/attachment.bin>
More information about the Libc-alpha
mailing list