You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
5.2 KiB
192 lines
5.2 KiB
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 --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c |
|
index 7babd947aa902e77..327802b14c7326a3 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)
|
|
|