1 /* Determine various system internal values, Linux version.
2 Copyright (C) 1996-2013 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/>. */
29 #include <stdio_ext.h>
33 #include <sys/sysinfo.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
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) \
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 \
65 while ((l = next_line (FD, BUFFER, &CP, &RE, BUFFER_END)) != NULL) \
66 if (strncmp (l, "processor", 9) == 0) \
74 next_line (int fd
, char *const buffer
, char **cp
, char **re
,
75 char *const buffer_end
)
78 char *nl
= memchr (*cp
, '\n', *re
- *cp
);
83 if (*re
== buffer_end
)
85 memmove (buffer
, *cp
, *re
- *cp
);
86 *re
= buffer
+ (*re
- *cp
);
89 ssize_t n
= read_not_cancel (fd
, *re
, buffer_end
- *re
);
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
);
104 nl
= memchr (*re
, '\n', n
);
110 nl
= memchr (*cp
, '\n', *re
- *cp
);
122 return res
== *re
? NULL
: res
;
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 ();
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
;
147 const int flags
= O_RDONLY
| O_CLOEXEC
;
149 const int flags
= O_RDONLY
;
151 int fd
= open_not_cancel_2 ("/sys/devices/system/cpu/online", flags
);
156 l
= next_line (fd
, buffer
, &cp
, &re
, buffer_end
);
161 unsigned long int n
= strtoul (l
, &endp
, 10);
168 unsigned long int m
= n
;
172 m
= strtoul (l
, &endp
, 10);
183 while (l
< re
&& isspace (*l
))
188 close_not_cancel_no_status (fd
);
198 /* The /proc/stat format is more uniform, use it by default. */
199 fd
= open_not_cancel_2 ("/proc/stat", flags
);
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)
209 else if (isdigit (l
[3]))
212 close_not_cancel_no_status (fd
);
216 fd
= open_not_cancel_2 ("/proc/cpuinfo", flags
);
219 GET_NPROCS_PARSER (fd
, buffer
, cp
, re
, buffer_end
, result
);
220 close_not_cancel_no_status (fd
);
225 cached_result
= result
;
226 atomic_write_barrier ();
231 weak_alias (__get_nprocs
, get_nprocs
)
234 /* On some architectures it is possible to distinguish between configured
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");
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)
254 unsigned long int nr
= strtoul (d
->d_name
+ 3, &endp
, 10);
255 if (nr
!= ULONG_MAX
&& endp
!= d
->d_name
+ 3 && *endp
== '\0')
266 #ifdef GET_NPROCS_CONF_PARSER
267 /* If we haven't found an appropriate entry return 1. */
268 FILE *fp
= fopen ("/proc/cpuinfo", "rce");
273 /* No threads use this stream. */
274 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
275 GET_NPROCS_CONF_PARSER (fp
, buffer
, result
);
279 result
= __get_nprocs ();
284 weak_alias (__get_nprocs_conf
, get_nprocs_conf
)
286 /* General function to get information about memory status from proc
290 phys_pages_info (const char *format
)
293 long int result
= -1;
295 /* If we haven't found an appropriate entry return 1. */
296 FILE *fp
= fopen ("/proc/meminfo", "rce");
299 /* No threads use this stream. */
300 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
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);
318 /* We cannot get the needed value: signal an error. */
319 __set_errno (ENOSYS
);
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
333 But not all systems have support for the /proc filesystem. If it
334 is not available we return -1 as an error signal. */
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
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
354 But not all systems have support for the /proc filesystem. If it
355 is not available we return -1 as an error signal. */
357 __get_avphys_pages ()
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
)