Update copyright notices with scripts/update-copyrights
[glibc.git] / sysdeps / unix / sysv / linux / getsysstats.c
blobb6a6fe3e2fa7b1c4c781a6adef87e56baeeff369
1 /* Determine various system internal values, Linux version.
2 Copyright (C) 1996-2014 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
20 #include <alloca.h>
21 #include <assert.h>
22 #include <ctype.h>
23 #include <dirent.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <mntent.h>
27 #include <paths.h>
28 #include <stdio.h>
29 #include <stdio_ext.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <sys/sysinfo.h>
35 #include <atomic.h>
36 #include <not-cancel.h>
37 #include <kernel-features.h>
40 /* How we can determine the number of available processors depends on
41 the configuration. There is currently (as of version 2.0.21) no
42 system call to determine the number. It is planned for the 2.1.x
43 series to add this, though.
45 One possibility to implement it for systems using Linux 2.0 is to
46 examine the pseudo file /proc/cpuinfo. Here we have one entry for
47 each processor.
49 But not all systems have support for the /proc filesystem. If it
50 is not available we simply return 1 since there is no way. */
53 /* Other architectures use different formats for /proc/cpuinfo. This
54 provides a hook for alternative parsers. */
55 #ifndef GET_NPROCS_PARSER
56 # define GET_NPROCS_PARSER(FD, BUFFER, CP, RE, BUFFER_END, RESULT) \
57 do \
58 { \
59 (RESULT) = 0; \
60 /* Read all lines and count the lines starting with the string \
61 "processor". We don't have to fear extremely long lines since \
62 the kernel will not generate them. 8192 bytes are really \
63 enough. */ \
64 char *l; \
65 while ((l = next_line (FD, BUFFER, &CP, &RE, BUFFER_END)) != NULL) \
66 if (strncmp (l, "processor", 9) == 0) \
67 ++(RESULT); \
68 } \
69 while (0)
70 #endif
73 static char *
74 next_line (int fd, char *const buffer, char **cp, char **re,
75 char *const buffer_end)
77 char *res = *cp;
78 char *nl = memchr (*cp, '\n', *re - *cp);
79 if (nl == NULL)
81 if (*cp != buffer)
83 if (*re == buffer_end)
85 memmove (buffer, *cp, *re - *cp);
86 *re = buffer + (*re - *cp);
87 *cp = buffer;
89 ssize_t n = read_not_cancel (fd, *re, buffer_end - *re);
90 if (n < 0)
91 return NULL;
93 *re += n;
95 nl = memchr (*cp, '\n', *re - *cp);
96 while (nl == NULL && *re == buffer_end)
98 /* Truncate too long lines. */
99 *re = buffer + 3 * (buffer_end - buffer) / 4;
100 n = read_not_cancel (fd, *re, buffer_end - *re);
101 if (n < 0)
102 return NULL;
104 nl = memchr (*re, '\n', n);
105 **re = '\n';
106 *re += n;
109 else
110 nl = memchr (*cp, '\n', *re - *cp);
112 res = *cp;
115 if (nl == NULL)
116 nl = *re - 1;
119 *cp = nl + 1;
120 assert (*cp <= *re);
122 return res == *re ? NULL : res;
127 __get_nprocs (void)
129 static int cached_result;
130 static time_t timestamp;
132 time_t now = time (NULL);
133 time_t prev = timestamp;
134 atomic_read_barrier ();
135 if (now == prev)
136 return cached_result;
138 /* XXX Here will come a test for the new system call. */
140 const size_t buffer_size = __libc_use_alloca (8192) ? 8192 : 512;
141 char *buffer = alloca (buffer_size);
142 char *buffer_end = buffer + buffer_size;
143 char *cp = buffer_end;
144 char *re = buffer_end;
146 #ifdef O_CLOEXEC
147 const int flags = O_RDONLY | O_CLOEXEC;
148 #else
149 const int flags = O_RDONLY;
150 #endif
151 int fd = open_not_cancel_2 ("/sys/devices/system/cpu/online", flags);
152 char *l;
153 int result = 0;
154 if (fd != -1)
156 l = next_line (fd, buffer, &cp, &re, buffer_end);
157 if (l != NULL)
160 char *endp;
161 unsigned long int n = strtoul (l, &endp, 10);
162 if (l == endp)
164 result = 0;
165 break;
168 unsigned long int m = n;
169 if (*endp == '-')
171 l = endp + 1;
172 m = strtoul (l, &endp, 10);
173 if (l == endp)
175 result = 0;
176 break;
180 result += m - n + 1;
182 l = endp;
183 while (l < re && isspace (*l))
184 ++l;
186 while (l < re);
188 close_not_cancel_no_status (fd);
190 if (result > 0)
191 goto out;
194 cp = buffer_end;
195 re = buffer_end;
196 result = 1;
198 /* The /proc/stat format is more uniform, use it by default. */
199 fd = open_not_cancel_2 ("/proc/stat", flags);
200 if (fd != -1)
202 result = 0;
204 while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL)
205 /* The current format of /proc/stat has all the cpu* entries
206 at the front. We assume here that stays this way. */
207 if (strncmp (l, "cpu", 3) != 0)
208 break;
209 else if (isdigit (l[3]))
210 ++result;
212 close_not_cancel_no_status (fd);
214 else
216 fd = open_not_cancel_2 ("/proc/cpuinfo", flags);
217 if (fd != -1)
219 GET_NPROCS_PARSER (fd, buffer, cp, re, buffer_end, result);
220 close_not_cancel_no_status (fd);
224 out:
225 cached_result = result;
226 atomic_write_barrier ();
227 timestamp = now;
229 return result;
231 weak_alias (__get_nprocs, get_nprocs)
234 /* On some architectures it is possible to distinguish between configured
235 and active cpus. */
237 __get_nprocs_conf (void)
239 /* XXX Here will come a test for the new system call. */
241 /* Try to use the sysfs filesystem. It has actual information about
242 online processors. */
243 DIR *dir = __opendir ("/sys/devices/system/cpu");
244 if (dir != NULL)
246 int count = 0;
247 struct dirent64 *d;
249 while ((d = __readdir64 (dir)) != NULL)
250 /* NB: the sysfs has d_type support. */
251 if (d->d_type == DT_DIR && strncmp (d->d_name, "cpu", 3) == 0)
253 char *endp;
254 unsigned long int nr = strtoul (d->d_name + 3, &endp, 10);
255 if (nr != ULONG_MAX && endp != d->d_name + 3 && *endp == '\0')
256 ++count;
259 __closedir (dir);
261 return count;
264 int result = 1;
266 #ifdef GET_NPROCS_CONF_PARSER
267 /* If we haven't found an appropriate entry return 1. */
268 FILE *fp = fopen ("/proc/cpuinfo", "rce");
269 if (fp != NULL)
271 char buffer[8192];
273 /* No threads use this stream. */
274 __fsetlocking (fp, FSETLOCKING_BYCALLER);
275 GET_NPROCS_CONF_PARSER (fp, buffer, result);
276 fclose (fp);
278 #else
279 result = __get_nprocs ();
280 #endif
282 return result;
284 weak_alias (__get_nprocs_conf, get_nprocs_conf)
286 /* General function to get information about memory status from proc
287 filesystem. */
288 static long int
289 internal_function
290 phys_pages_info (const char *format)
292 char buffer[8192];
293 long int result = -1;
295 /* If we haven't found an appropriate entry return 1. */
296 FILE *fp = fopen ("/proc/meminfo", "rce");
297 if (fp != NULL)
299 /* No threads use this stream. */
300 __fsetlocking (fp, FSETLOCKING_BYCALLER);
302 result = 0;
303 /* Read all lines and count the lines starting with the
304 string "processor". We don't have to fear extremely long
305 lines since the kernel will not generate them. 8192
306 bytes are really enough. */
307 while (fgets_unlocked (buffer, sizeof buffer, fp) != NULL)
308 if (sscanf (buffer, format, &result) == 1)
310 result /= (__getpagesize () / 1024);
311 break;
314 fclose (fp);
317 if (result == -1)
318 /* We cannot get the needed value: signal an error. */
319 __set_errno (ENOSYS);
321 return result;
325 /* Return the number of pages of physical memory in the system. There
326 is currently (as of version 2.0.21) no system call to determine the
327 number. It is planned for the 2.1.x series to add this, though.
329 One possibility to implement it for systems using Linux 2.0 is to
330 examine the pseudo file /proc/cpuinfo. Here we have one entry for
331 each processor.
333 But not all systems have support for the /proc filesystem. If it
334 is not available we return -1 as an error signal. */
335 long int
336 __get_phys_pages (void)
338 /* XXX Here will come a test for the new system call. */
340 return phys_pages_info ("MemTotal: %ld kB");
342 weak_alias (__get_phys_pages, get_phys_pages)
345 /* Return the number of available pages of physical memory in the
346 system. There is currently (as of version 2.0.21) no system call
347 to determine the number. It is planned for the 2.1.x series to add
348 this, though.
350 One possibility to implement it for systems using Linux 2.0 is to
351 examine the pseudo file /proc/cpuinfo. Here we have one entry for
352 each processor.
354 But not all systems have support for the /proc filesystem. If it
355 is not available we return -1 as an error signal. */
356 long int
357 __get_avphys_pages (void)
359 /* XXX Here will come a test for the new system call. */
361 return phys_pages_info ("MemFree: %ld kB");
363 weak_alias (__get_avphys_pages, get_avphys_pages)