diff mbox series

[3/4] linux: Use /sys/devices/system/cpu/possible on __get_nprocs_conf

Message ID 20210329182520.323665-3-adhemerval.zanella@linaro.org
State New
Headers show
Series [1/4] Remove architecture specific sched_cpucount optimizations | expand

Commit Message

Adhemerval Zanella March 29, 2021, 6:25 p.m. UTC
Instead of iterate over all the cpu in the sysfs folder.  It consumes
slight less resources on large system (which might require extra
getdents call) and memory (a limited stack buffer instead a large
malloced one for opendir).

Checked on x86_64-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
---
 sysdeps/unix/sysv/linux/getsysstats.c | 51 +++++++++++++++------------
 1 file changed, 29 insertions(+), 22 deletions(-)
diff mbox series

Patch

diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
index f8a4a31d1b..5069951246 100644
--- a/sysdeps/unix/sysv/linux/getsysstats.c
+++ b/sysdeps/unix/sysv/linux/getsysstats.c
@@ -17,7 +17,8 @@ 
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <dirent.h>
+#include <ctype.h>
+#include <intprops.h>
 #include <not-cancel.h>
 #include <scratch_buffer.h>
 #include <stdio.h>
@@ -63,33 +64,39 @@  weak_alias (__get_nprocs, get_nprocs)
 int
 __get_nprocs_conf (void)
 {
-  /* XXX Here will come a test for the new system call.  */
+  int result = 1;
 
   /* Try to use the sysfs filesystem.  It has actual information about
      online processors.  */
-  DIR *dir = __opendir ("/sys/devices/system/cpu");
-  if (dir != NULL)
+  int fd = __open64_nocancel ("/sys/devices/system/cpu/possible", O_RDONLY);
+  if (fd != -1)
     {
-      int count = 0;
-      struct dirent64 *d;
-
-      while ((d = __readdir64 (dir)) != NULL)
-	/* NB: the sysfs has d_type support.  */
-	if (d->d_type == DT_DIR && strncmp (d->d_name, "cpu", 3) == 0)
-	  {
-	    char *endp;
-	    unsigned long int nr = strtoul (d->d_name + 3, &endp, 10);
-	    if (nr != ULONG_MAX && endp != d->d_name + 3 && *endp == '\0')
-	      ++count;
-	  }
-
-      __closedir (dir);
-
-      return count;
+      /* The entry is in the form of '[cpuX]-[cpuY]'.  */
+      char buf[2 * INT_STRLEN_BOUND (unsigned int) + 1];
+
+      ssize_t n = __read_nocancel (fd, buf, sizeof (buf));
+      if (n > 0)
+	{
+	  buf[n] = '\0';
+
+	  /* Start on the right, to find highest node number.  */
+	  int m = 1;
+	  while (--n)
+	    {
+	      if ((buf[n] == ',') || (buf[n] == '-'))
+		break;
+	      /* Ignore '\n'  */
+	      if (! isdigit (buf[n]))
+		continue;
+	      result += (buf[n] - '0') * m;
+	      m *= 10;
+	    }
+	}
+
+      __close_nocancel (fd);
+      return result + 1;
     }
 
-  int result = 1;
-
 #ifdef GET_NPROCS_CONF_PARSER
   /* If we haven't found an appropriate entry return 1.  */
   FILE *fp = fopen ("/proc/cpuinfo", "rce");