On Android, inside Termux, I see the test-getloadavg test fail.

This patch fixes it, by using the sysinfo() system call instead
of reading from /proc. Like what was done in glibc in 2021:
<https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b5c8a3aa82f66f49b731ca5204104cee48bccfa5>


2025-03-21  Bruno Haible  <br...@clisp.org>

        getloadavg: Improve Linux and Android support.
        * lib/getloadavg.c [__linux__, __ANDROID__]: Include <sys/param.h> and
        <sys/sysinfo.h>.
        (getloadavg) [__linux__, __ANDROID__]: Use sysinfo() instead of reading
        /proc/loadavg.
        (LINUX_LDAV_FILE): Remove macro.

diff --git a/lib/getloadavg.c b/lib/getloadavg.c
index cdf4514be8..9da41c16c0 100644
--- a/lib/getloadavg.c
+++ b/lib/getloadavg.c
@@ -47,8 +47,6 @@
    N_NAME_POINTER               The nlist n_name element is a pointer,
                                 not an array.
    HAVE_STRUCT_NLIST_N_UN_N_NAME 'n_un.n_name' is member of 'struct nlist'.
-   LINUX_LDAV_FILE              [__linux__, __ANDROID__, __CYGWIN__]: File
-                                containing load averages.
 
    Specific system predefines this file uses, aside from setting
    default values if not emacs:
@@ -65,8 +63,7 @@
    UMAX4_3
    VMS
    _WIN32                       Native Windows (possibly also defined on 
Cygwin)
-   __linux__, __ANDROID__       Linux: assumes /proc file system mounted.
-                                Support from Michael K. Johnson.
+   __linux__, __ANDROID__       Linux: assumes sysinfo() call.
    __CYGWIN__                   Cygwin emulates linux /proc/loadavg.
    __NetBSD__                   NetBSD: assumes /kern file system mounted.
 
@@ -357,6 +354,11 @@
 #  include <sys/dg_sys_info.h>
 # endif
 
+# if defined __linux__ || defined __ANDROID__
+#  include <sys/param.h>
+#  include <sys/sysinfo.h>
+# endif
+
 # if (defined __linux__ || defined __ANDROID__ \
       || defined __CYGWIN__ || defined SUNOS_5 \
       || (defined LOAD_AVE_TYPE && ! defined __VMS))
@@ -497,20 +499,32 @@ getloadavg (double loadavg[], int nelem)
   }
 # endif
 
-# if !defined (LDAV_DONE) && (defined __linux__ || defined __ANDROID__ || 
defined __CYGWIN__)
+# if !defined (LDAV_DONE) && (defined __linux__ || defined __ANDROID__)
                                       /* Linux without glibc, Android, Cygwin 
*/
 #  define LDAV_DONE
 #  undef LOAD_AVE_TYPE
 
-#  ifndef LINUX_LDAV_FILE
-#   define LINUX_LDAV_FILE "/proc/loadavg"
-#  endif
+  {
+    struct sysinfo info;
+    if (sysinfo (&info) < 0)
+      return -1;
+    loadavg[0] = info.loads[0] / (double)(1U << SI_LOAD_SHIFT);
+    loadavg[1] = info.loads[1] / (double)(1U << SI_LOAD_SHIFT);
+    loadavg[2] = info.loads[2] / (double)(1U << SI_LOAD_SHIFT);
+    elem = 3;
+  }
+# endif /* __linux__ || __ANDROID__ */
+
+# if !defined (LDAV_DONE) && defined __CYGWIN__
+                                      /* Cygwin */
+#  define LDAV_DONE
+#  undef LOAD_AVE_TYPE
 
   char ldavgbuf[3 * (INT_STRLEN_BOUND (int) + sizeof ".00 ")];
   char const *ptr = ldavgbuf;
   int fd, count, saved_errno;
 
-  fd = open (LINUX_LDAV_FILE, O_RDONLY | O_CLOEXEC);
+  fd = open ("/proc/loadavg", O_RDONLY | O_CLOEXEC);
   if (fd == -1)
     return -1;
   count = read (fd, ldavgbuf, sizeof ldavgbuf - 1);
@@ -553,7 +567,7 @@ getloadavg (double loadavg[], int nelem)
 
   return elem;
 
-# endif /* __linux__ || __ANDROID__ || __CYGWIN__ */
+# endif /* __CYGWIN__ */
 
 # if !defined (LDAV_DONE) && defined (__NetBSD__)          /* NetBSD < 0.9 */
 #  define LDAV_DONE




Reply via email to