summaryrefslogtreecommitdiff
path: root/linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch
diff options
context:
space:
mode:
Diffstat (limited to 'linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch')
-rw-r--r--linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch212
1 files changed, 212 insertions, 0 deletions
diff --git a/linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch b/linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch
new file mode 100644
index 0000000..d16fa75
--- /dev/null
+++ b/linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch
@@ -0,0 +1,212 @@
+From 007e054d786be340699c634e3a3b30ab1fde1a7a Mon Sep 17 00:00:00 2001
+From: "Dmitry V. Levin" <ldv@altlinux.org>
+Date: Sat, 5 Feb 2022 08:00:00 +0000
+Subject: [PATCH] linux: fix accuracy of get_nprocs and get_nprocs_conf [BZ
+ #28865]
+
+get_nprocs() and get_nprocs_conf() use various methods to obtain an
+accurate number of processors. Re-introduce __get_nprocs_sched() as
+a source of information, and fix the order in which these methods are
+used to return the most accurate information. The primary source of
+information used in both functions remains unchanged.
+
+This also changes __get_nprocs_sched() error return value from 2 to 0,
+but all its users are already prepared to handle that.
+
+Old fallback order:
+ get_nprocs:
+ /sys/devices/system/cpu/online -> /proc/stat -> 2
+ get_nprocs_conf:
+ /sys/devices/system/cpu/ -> /proc/stat -> 2
+
+New fallback order:
+ get_nprocs:
+ /sys/devices/system/cpu/online -> /proc/stat -> sched_getaffinity -> 2
+ get_nprocs_conf:
+ /sys/devices/system/cpu/ -> /proc/stat -> sched_getaffinity -> 2
+
+Fixes: 342298278e ("linux: Revert the use of sched_getaffinity on get_nproc")
+Closes: BZ #28865
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+
+(cherry picked from commit e1d32b836410767270a3adf1f82b1a47e6e4cd51)
+---
+ NEWS | 2 +
+ sysdeps/unix/sysv/linux/getsysstats.c | 94 ++++++++++++++++++---------
+ 2 files changed, 65 insertions(+), 31 deletions(-)
+
+diff --git a/NEWS b/NEWS
+index 87c9517e1a..aef051122e 100644
+--- a/NEWS
++++ b/NEWS
+@@ -29,6 +29,8 @@ The following bugs are resolved with this release:
+ [28349] libc: Segfault for ping -R on qemux86 caused by recvmsg()
+ [28350] libc: ping receives SIGABRT on lib32-qemux86-64 caused by
+ recvmsg()
++ [28865] linux: _SC_NPROCESSORS_CONF and _SC_NPROCESSORS_ONLN are inaccurate
++ without /sys and /proc
+
+
+ Version 2.34
+diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
+index 7babd947aa..327802b14c 100644
+--- a/sysdeps/unix/sysv/linux/getsysstats.c
++++ b/sysdeps/unix/sysv/linux/getsysstats.c
+@@ -51,9 +51,8 @@ __get_nprocs_sched (void)
+ is an arbitrary values assuming such systems should be rare and there
+ is no offline cpus. */
+ return max_num_cpus;
+- /* Some other error. 2 is conservative (not a uniprocessor system, so
+- atomics are needed). */
+- return 2;
++ /* Some other error. */
++ return 0;
+ }
+
+ static char *
+@@ -109,22 +108,19 @@ next_line (int fd, char *const buffer, char **cp, char **re,
+ }
+
+ static int
+-get_nproc_stat (char *buffer, size_t buffer_size)
++get_nproc_stat (void)
+ {
++ enum { buffer_size = 1024 };
++ char buffer[buffer_size];
+ char *buffer_end = buffer + buffer_size;
+ char *cp = buffer_end;
+ char *re = buffer_end;
+-
+- /* Default to an SMP system in case we cannot obtain an accurate
+- number. */
+- int result = 2;
++ int result = 0;
+
+ const int flags = O_RDONLY | O_CLOEXEC;
+ int fd = __open_nocancel ("/proc/stat", flags);
+ if (fd != -1)
+ {
+- result = 0;
+-
+ char *l;
+ while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL)
+ /* The current format of /proc/stat has all the cpu* entries
+@@ -140,8 +136,8 @@ get_nproc_stat (char *buffer, size_t buffer_size)
+ return result;
+ }
+
+-int
+-__get_nprocs (void)
++static int
++get_nprocs_cpu_online (void)
+ {
+ enum { buffer_size = 1024 };
+ char buffer[buffer_size];
+@@ -180,7 +176,8 @@ __get_nprocs (void)
+ }
+ }
+
+- result += m - n + 1;
++ if (m >= n)
++ result += m - n + 1;
+
+ l = endp;
+ if (l < re && *l == ',')
+@@ -189,28 +186,18 @@ __get_nprocs (void)
+ while (l < re && *l != '\n');
+
+ __close_nocancel_nostatus (fd);
+-
+- if (result > 0)
+- return result;
+ }
+
+- return get_nproc_stat (buffer, buffer_size);
++ return result;
+ }
+-libc_hidden_def (__get_nprocs)
+-weak_alias (__get_nprocs, get_nprocs)
+-
+
+-/* On some architectures it is possible to distinguish between configured
+- and active cpus. */
+-int
+-__get_nprocs_conf (void)
++static int
++get_nprocs_cpu (void)
+ {
+- /* Try to use the sysfs filesystem. It has actual information about
+- online processors. */
++ int count = 0;
+ DIR *dir = __opendir ("/sys/devices/system/cpu");
+ if (dir != NULL)
+ {
+- int count = 0;
+ struct dirent64 *d;
+
+ while ((d = __readdir64 (dir)) != NULL)
+@@ -225,12 +212,57 @@ __get_nprocs_conf (void)
+
+ __closedir (dir);
+
+- return count;
+ }
++ return count;
++}
+
+- enum { buffer_size = 1024 };
+- char buffer[buffer_size];
+- return get_nproc_stat (buffer, buffer_size);
++static int
++get_nprocs_fallback (void)
++{
++ int result;
++
++ /* Try /proc/stat first. */
++ result = get_nproc_stat ();
++ if (result != 0)
++ return result;
++
++ /* Try sched_getaffinity. */
++ result = __get_nprocs_sched ();
++ if (result != 0)
++ return result;
++
++ /* We failed to obtain an accurate number. Be conservative: return
++ the smallest number meaning that this is not a uniprocessor system,
++ so atomics are needed. */
++ return 2;
++}
++
++int
++__get_nprocs (void)
++{
++ /* Try /sys/devices/system/cpu/online first. */
++ int result = get_nprocs_cpu_online ();
++ if (result != 0)
++ return result;
++
++ /* Fall back to /proc/stat and sched_getaffinity. */
++ return get_nprocs_fallback ();
++}
++libc_hidden_def (__get_nprocs)
++weak_alias (__get_nprocs, get_nprocs)
++
++/* On some architectures it is possible to distinguish between configured
++ and active cpus. */
++int
++__get_nprocs_conf (void)
++{
++ /* Try /sys/devices/system/cpu/ first. */
++ int result = get_nprocs_cpu ();
++ if (result != 0)
++ return result;
++
++ /* Fall back to /proc/stat and sched_getaffinity. */
++ return get_nprocs_fallback ();
+ }
+ libc_hidden_def (__get_nprocs_conf)
+ weak_alias (__get_nprocs_conf, get_nprocs_conf)
+--
+2.27.0
+