diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux/getsysstats.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/getsysstats.c | 109 |
1 files changed, 94 insertions, 15 deletions
diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c index d655ba3b27..ee7a539a6f 100644 --- a/sysdeps/unix/sysv/linux/getsysstats.c +++ b/sysdeps/unix/sysv/linux/getsysstats.c @@ -1,5 +1,5 @@ /* Determine various system internal values, Linux version. - Copyright (C) 1996-2001, 2002, 2003, 2006 Free Software Foundation, Inc. + Copyright (C) 1996-2001, 2002, 2003, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -21,7 +21,9 @@ #include <alloca.h> #include <assert.h> #include <ctype.h> +#include <dirent.h> #include <errno.h> +#include <fcntl.h> #include <mntent.h> #include <paths.h> #include <stdio.h> @@ -32,6 +34,7 @@ #include <sys/sysinfo.h> #include <atomic.h> +#include <not-cancel.h> /* How we can determine the number of available processors depends on @@ -64,14 +67,13 @@ while (0) #endif -int -__get_nprocs () + +static int +count_processors_in_proc (void) { char buffer[8192]; int result = 1; - /* XXX Here will come a test for the new system call. */ - /* The /proc/stat format is more uniform, use it by default. */ FILE *fp = fopen ("/proc/stat", "rc"); if (fp != NULL) @@ -100,38 +102,115 @@ __get_nprocs () return result; } + + +int +__get_nprocs () +{ + /* XXX Here will come a test for the new system call. */ + + /* Try to use the sysfs filesystem. It has actual information about + online processors. */ + DIR *dir = __opendir ("/sys/devices/system/cpu"); + if (dir != NULL) + { + int dfd = dirfd (dir); + 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') + { + /* Try reading the online file. */ + char oname[_D_ALLOC_NAMLEN (d) + sizeof "/online"]; + strcpy (stpcpy (oname, d->d_name), "/online"); + + /* We unconditionally use openat since the "online" + file became readable only after the openat system + call was introduced. */ + char buf[1]; + int fd = openat_not_cancel_3 (dfd, oname, O_RDONLY); + + /* If we cannot read the online file we have to assume + the CPU is online. */ + if (fd < 0) + ++count; + else + { + if (read_not_cancel (fd, buf, sizeof (buf)) < 0 + || buf[0] == '1') + ++count; + + close_not_cancel_no_status (fd); + } + } + } + + __closedir (dir); + + return count; + } + + return count_processors_in_proc (); +} weak_alias (__get_nprocs, get_nprocs) -#ifdef GET_NPROCS_CONF_PARSER /* On some architectures it is possible to distinguish between configured and active cpus. */ int __get_nprocs_conf () { - char buffer[8192]; - int result = 1; - /* XXX Here will come a test for the new system call. */ + /* Try to use the sysfs filesystem. It has actual information about + online processors. */ + DIR *dir = __opendir ("/sys/devices/system/cpu"); + if (dir != NULL) + { + 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; + } + + int result = 1; + +#ifdef GET_NPROCS_CONF_PARSER /* If we haven't found an appropriate entry return 1. */ FILE *fp = fopen ("/proc/cpuinfo", "rc"); if (fp != NULL) { + char buffer[8192]; + /* No threads use this stream. */ __fsetlocking (fp, FSETLOCKING_BYCALLER); GET_NPROCS_CONF_PARSER (fp, buffer, result); fclose (fp); } +#else + result = count_processors_in_proc (); +#endif return result; } -#else -/* As far as I know Linux has no separate numbers for configured and - available processors. So make the `get_nprocs_conf' function an - alias. */ -strong_alias (__get_nprocs, __get_nprocs_conf) -#endif weak_alias (__get_nprocs_conf, get_nprocs_conf) /* General function to get information about memory status from proc |