1 /* Determine various system internal values, Linux version.
2 Copyright (C) 1996-2003, 2006, 2007, 2009 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, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
30 #include <stdio_ext.h>
34 #include <sys/sysinfo.h>
37 #include <not-cancel.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. */
52 #include <not-cancel.h>
55 /* Other architectures use different formats for /proc/cpuinfo. This
56 provides a hook for alternative parsers. */
57 #ifndef GET_NPROCS_PARSER
58 # define GET_NPROCS_PARSER(FD, BUFFER, CP, RE, BUFFER_END, RESULT) \
62 /* Read all lines and count the lines starting with the string \
63 "processor". We don't have to fear extremely long lines since \
64 the kernel will not generate them. 8192 bytes are really \
67 while ((l = next_line (FD, BUFFER, &CP, &RE, BUFFER_END)) != NULL) \
68 if (strncmp (l, "processor", 9) == 0) \
76 next_line (int fd
, char *const buffer
, char **cp
, char **re
,
77 char *const buffer_end
)
80 char *nl
= memchr (*cp
, '\n', *re
- *cp
);
85 if (*re
== buffer_end
)
87 memmove (buffer
, *cp
, *re
- *cp
);
88 *re
= buffer
+ (*re
- *cp
);
91 ssize_t n
= read_not_cancel (fd
, *re
, buffer_end
- *re
);
97 nl
= memchr (*cp
, '\n', *re
- *cp
);
98 while (nl
== NULL
&& *re
== buffer_end
)
100 /* Truncate too long lines. */
101 *re
= buffer
+ 3 * (buffer_end
- buffer
) / 4;
102 n
= read_not_cancel (fd
, *re
, buffer_end
- *re
);
106 nl
= memchr (*re
, '\n', n
);
112 nl
= memchr (*cp
, '\n', *re
- *cp
);
120 else if (nl
+ 5 >= *re
)
122 memmove (buffer
, nl
, *re
- nl
);
123 *re
= buffer
+ (*re
- nl
);
126 ssize_t n
= read_not_cancel (fd
, *re
, buffer_end
- *re
);
136 return res
== *re
? NULL
: res
;
143 /* XXX Here will come a test for the new system call. */
145 const size_t buffer_size
= __libc_use_alloca (8192) ? 8192 : 512;
146 char *buffer
= alloca (buffer_size
);
147 char *buffer_end
= buffer
+ buffer_size
;
148 char *cp
= buffer_end
;
149 char *re
= buffer_end
;
153 const int flags
= O_RDONLY
| O_CLOEXEC
;
155 const int flags
= O_RDONLY
;
157 /* The /proc/stat format is more uniform, use it by default. */
158 int fd
= open_not_cancel_2 ("/proc/stat", flags
);
164 while ((l
= next_line (fd
, buffer
, &cp
, &re
, buffer_end
)) != NULL
)
165 /* The current format of /proc/stat has all the cpu* entries
166 at the front. We assume here that stays this way. */
167 if (strncmp (l
, "cpu", 3) != 0)
169 else if (isdigit (l
[3]))
172 close_not_cancel_no_status (fd
);
176 fd
= open_not_cancel_2 ("/proc/cpuinfo", flags
);
179 GET_NPROCS_PARSER (fd
, buffer
, cp
, re
, buffer_end
, result
);
180 close_not_cancel_no_status (fd
);
186 weak_alias (__get_nprocs
, get_nprocs
)
189 /* On some architectures it is possible to distinguish between configured
194 /* XXX Here will come a test for the new system call. */
196 /* Try to use the sysfs filesystem. It has actual information about
197 online processors. */
198 DIR *dir
= __opendir ("/sys/devices/system/cpu");
204 while ((d
= __readdir64 (dir
)) != NULL
)
205 /* NB: the sysfs has d_type support. */
206 if (d
->d_type
== DT_DIR
&& strncmp (d
->d_name
, "cpu", 3) == 0)
209 unsigned long int nr
= strtoul (d
->d_name
+ 3, &endp
, 10);
210 if (nr
!= ULONG_MAX
&& endp
!= d
->d_name
+ 3 && *endp
== '\0')
221 #ifdef GET_NPROCS_CONF_PARSER
222 /* If we haven't found an appropriate entry return 1. */
223 FILE *fp
= fopen ("/proc/cpuinfo", "rce");
228 /* No threads use this stream. */
229 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
230 GET_NPROCS_CONF_PARSER (fp
, buffer
, result
);
234 result
= __get_nprocs ();
239 weak_alias (__get_nprocs_conf
, get_nprocs_conf
)
241 /* General function to get information about memory status from proc
245 phys_pages_info (const char *format
)
248 long int result
= -1;
250 /* If we haven't found an appropriate entry return 1. */
251 FILE *fp
= fopen ("/proc/meminfo", "rc");
254 /* No threads use this stream. */
255 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
258 /* Read all lines and count the lines starting with the
259 string "processor". We don't have to fear extremely long
260 lines since the kernel will not generate them. 8192
261 bytes are really enough. */
262 while (fgets_unlocked (buffer
, sizeof buffer
, fp
) != NULL
)
263 if (sscanf (buffer
, format
, &result
) == 1)
265 result
/= (__getpagesize () / 1024);
273 /* We cannot get the needed value: signal an error. */
274 __set_errno (ENOSYS
);
280 /* Return the number of pages of physical memory in the system. There
281 is currently (as of version 2.0.21) no system call to determine the
282 number. It is planned for the 2.1.x series to add this, though.
284 One possibility to implement it for systems using Linux 2.0 is to
285 examine the pseudo file /proc/cpuinfo. Here we have one entry for
288 But not all systems have support for the /proc filesystem. If it
289 is not available we return -1 as an error signal. */
293 /* XXX Here will come a test for the new system call. */
295 return phys_pages_info ("MemTotal: %ld kB");
297 weak_alias (__get_phys_pages
, get_phys_pages
)
300 /* Return the number of available pages of physical memory in the
301 system. There is currently (as of version 2.0.21) no system call
302 to determine the number. It is planned for the 2.1.x series to add
305 One possibility to implement it for systems using Linux 2.0 is to
306 examine the pseudo file /proc/cpuinfo. Here we have one entry for
309 But not all systems have support for the /proc filesystem. If it
310 is not available we return -1 as an error signal. */
312 __get_avphys_pages ()
314 /* XXX Here will come a test for the new system call. */
316 return phys_pages_info ("MemFree: %ld kB");
318 weak_alias (__get_avphys_pages
, get_avphys_pages
)