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