]>
Commit | Line | Data |
---|---|---|
f2b22ab7 MT |
1 | diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c |
2 | index af454b6..249bd19 100644 | |
3 | --- a/sysdeps/unix/sysv/linux/getsysstats.c | |
4 | +++ b/sysdeps/unix/sysv/linux/getsysstats.c | |
5 | @@ -35,6 +34,7 @@ | |
6 | ||
7 | #include <atomic.h> | |
8 | #include <not-cancel.h> | |
9 | +#include <kernel-features.h> | |
10 | ||
11 | ||
12 | /* How we can determine the number of available processors depends on | |
13 | @@ -49,8 +49,6 @@ | |
14 | But not all systems have support for the /proc filesystem. If it | |
15 | is not available we simply return 1 since there is no way. */ | |
16 | ||
17 | -#include <not-cancel.h> | |
18 | - | |
19 | ||
20 | /* Other architectures use different formats for /proc/cpuinfo. This | |
21 | provides a hook for alternative parsers. */ | |
22 | @@ -128,6 +126,15 @@ next_line (int fd, char *const buffer, char **cp, char **re, | |
23 | int | |
24 | __get_nprocs () | |
25 | { | |
26 | + static int cached_result; | |
27 | + static time_t timestamp; | |
28 | + | |
29 | + time_t now = time (NULL); | |
30 | + time_t prev = timestamp; | |
31 | + atomic_read_barrier (); | |
32 | + if (now == prev) | |
33 | + return cached_result; | |
34 | + | |
35 | /* XXX Here will come a test for the new system call. */ | |
36 | ||
37 | const size_t buffer_size = __libc_use_alloca (8192) ? 8192 : 512; | |
38 | @@ -135,20 +142,65 @@ __get_nprocs () | |
39 | char *buffer_end = buffer + buffer_size; | |
40 | char *cp = buffer_end; | |
41 | char *re = buffer_end; | |
42 | - int result = 1; | |
43 | ||
44 | #ifdef O_CLOEXEC | |
45 | const int flags = O_RDONLY | O_CLOEXEC; | |
46 | #else | |
47 | const int flags = O_RDONLY; | |
48 | #endif | |
49 | + int fd = open_not_cancel_2 ("/sys/devices/system/cpu/online", flags); | |
50 | + char *l; | |
51 | + int result = 0; | |
52 | + if (fd != -1) | |
53 | + { | |
54 | + l = next_line (fd, buffer, &cp, &re, buffer_end); | |
55 | + if (l != NULL) | |
56 | + do | |
57 | + { | |
58 | + char *endp; | |
59 | + unsigned long int n = strtoul (l, &endp, 10); | |
60 | + if (l == endp) | |
61 | + { | |
62 | + result = 0; | |
63 | + break; | |
64 | + } | |
65 | + | |
66 | + unsigned long int m = n; | |
67 | + if (*endp == '-') | |
68 | + { | |
69 | + l = endp + 1; | |
70 | + m = strtoul (l, &endp, 10); | |
71 | + if (l == endp) | |
72 | + { | |
73 | + result = 0; | |
74 | + break; | |
75 | + } | |
76 | + } | |
77 | + | |
78 | + result += m - n + 1; | |
79 | + | |
80 | + l = endp; | |
81 | + while (l < re && isspace (*l)) | |
82 | + ++l; | |
83 | + } | |
84 | + while (l < re); | |
85 | + | |
86 | + close_not_cancel_no_status (fd); | |
87 | + | |
88 | + if (result > 0) | |
89 | + goto out; | |
90 | + } | |
91 | + | |
92 | + cp = buffer_end; | |
93 | + re = buffer_end; | |
94 | + result = 1; | |
95 | + | |
96 | /* The /proc/stat format is more uniform, use it by default. */ | |
97 | - int fd = open_not_cancel_2 ("/proc/stat", flags); | |
98 | + fd = open_not_cancel_2 ("/proc/stat", flags); | |
99 | if (fd != -1) | |
100 | { | |
101 | result = 0; | |
102 | ||
103 | - char *l; | |
104 | while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL) | |
105 | /* The current format of /proc/stat has all the cpu* entries | |
106 | at the front. We assume here that stays this way. */ | |
107 | @@ -169,6 +221,11 @@ __get_nprocs () | |
108 | } | |
109 | } | |
110 | ||
111 | + out: | |
112 | + cached_result = result; | |
113 | + atomic_write_barrier (); | |
114 | + timestamp = now; | |
115 | + | |
116 | return result; | |
117 | } | |
118 | weak_alias (__get_nprocs, get_nprocs) | |
119 | @@ -236,7 +293,7 @@ phys_pages_info (const char *format) | |
120 | long int result = -1; | |
121 | ||
122 | /* If we haven't found an appropriate entry return 1. */ | |
123 | - FILE *fp = fopen ("/proc/meminfo", "rc"); | |
124 | + FILE *fp = fopen ("/proc/meminfo", "rce"); | |
125 | if (fp != NULL) | |
126 | { | |
127 | /* No threads use this stream. */ |