public inbox for glibc-cvs@sourceware.org
help / color / mirror / Atom feed
* [glibc/release/2.34/master] linux: fix accuracy of get_nprocs and get_nprocs_conf [BZ #28865]
@ 2022-02-08 22:34 Dmitry Levin
  0 siblings, 0 replies; only message in thread
From: Dmitry Levin @ 2022-02-08 22:34 UTC (permalink / raw)
  To: glibc-cvs

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=007e054d786be340699c634e3a3b30ab1fde1a7a

commit 007e054d786be340699c634e3a3b30ab1fde1a7a
Author: Dmitry V. Levin <ldv@altlinux.org>
Date:   Sat Feb 5 08:00:00 2022 +0000

    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)

Diff:
---
 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
@@ -63,6 +63,8 @@ The following bugs are resolved with this release:
   [28850] linux: __get_nprocs_sched reads uninitialized memory from the stack
   [28860] build: --enable-kernel=5.1.0 build fails because of missing
     __convert_scm_timestamps
+  [28865] linux: _SC_NPROCESSORS_CONF and _SC_NPROCESSORS_ONLN are inaccurate
+    without /sys and /proc
 
 \f
 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)


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-02-08 22:34 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-08 22:34 [glibc/release/2.34/master] linux: fix accuracy of get_nprocs and get_nprocs_conf [BZ #28865] Dmitry Levin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).