]>
Commit | Line | Data |
---|---|---|
dfd2257a | 1 | /* Determine various system internal values, Linux version. |
58d43ba8 | 2 | Copyright (C) 1996-2001, 2002, 2003, 2006, 2007 Free Software Foundation, Inc. |
84384f5b UD |
3 | This file is part of the GNU C Library. |
4 | Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. | |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
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. | |
84384f5b UD |
10 | |
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 | |
41bdb6e2 | 14 | Lesser General Public License for more details. |
84384f5b | 15 | |
41bdb6e2 AJ |
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 | |
19 | 02111-1307 USA. */ | |
84384f5b UD |
20 | |
21 | #include <alloca.h> | |
77432371 | 22 | #include <assert.h> |
27692f89 | 23 | #include <ctype.h> |
58d43ba8 | 24 | #include <dirent.h> |
845dcb57 | 25 | #include <errno.h> |
58d43ba8 | 26 | #include <fcntl.h> |
845dcb57 | 27 | #include <mntent.h> |
46ec036d | 28 | #include <paths.h> |
845dcb57 | 29 | #include <stdio.h> |
2706ee38 | 30 | #include <stdio_ext.h> |
77432371 | 31 | #include <stdlib.h> |
845dcb57 UD |
32 | #include <string.h> |
33 | #include <unistd.h> | |
34 | #include <sys/sysinfo.h> | |
35 | ||
4009bf40 | 36 | #include <atomic.h> |
58d43ba8 | 37 | #include <not-cancel.h> |
77432371 UD |
38 | |
39 | ||
845dcb57 UD |
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. | |
44 | ||
45 | One possibility to implement it for systems using Linux 2.0 is to | |
b0b67c47 | 46 | examine the pseudo file /proc/cpuinfo. Here we have one entry for |
845dcb57 UD |
47 | each processor. |
48 | ||
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. */ | |
bdb04ee8 UD |
51 | |
52 | /* Other architectures use different formats for /proc/cpuinfo. This | |
53 | provides a hook for alternative parsers. */ | |
54 | #ifndef GET_NPROCS_PARSER | |
55 | # define GET_NPROCS_PARSER(FP, BUFFER, RESULT) \ | |
56 | do \ | |
57 | { \ | |
58 | (RESULT) = 0; \ | |
59 | /* Read all lines and count the lines starting with the string \ | |
60 | "processor". We don't have to fear extremely long lines since \ | |
61 | the kernel will not generate them. 8192 bytes are really \ | |
62 | enough. */ \ | |
63 | while (fgets_unlocked (BUFFER, sizeof (BUFFER), FP) != NULL) \ | |
64 | if (strncmp (BUFFER, "processor", 9) == 0) \ | |
65 | ++(RESULT); \ | |
66 | } \ | |
67 | while (0) | |
68 | #endif | |
69 | ||
9506149a | 70 | |
0abf17de UD |
71 | int |
72 | __get_nprocs () | |
845dcb57 | 73 | { |
0abf17de UD |
74 | /* XXX Here will come a test for the new system call. */ |
75 | ||
845dcb57 | 76 | char buffer[8192]; |
845dcb57 UD |
77 | int result = 1; |
78 | ||
9506149a UD |
79 | /* The /proc/stat format is more uniform, use it by default. */ |
80 | FILE *fp = fopen ("/proc/stat", "rc"); | |
81 | if (fp != NULL) | |
82 | { | |
83 | /* No threads use this stream. */ | |
84 | __fsetlocking (fp, FSETLOCKING_BYCALLER); | |
85 | ||
86 | result = 0; | |
87 | while (fgets_unlocked (buffer, sizeof (buffer), fp) != NULL) | |
88 | if (strncmp (buffer, "cpu", 3) == 0 && isdigit (buffer[3])) | |
89 | ++result; | |
90 | ||
91 | fclose (fp); | |
92 | } | |
93 | else | |
94 | { | |
95 | fp = fopen ("/proc/cpuinfo", "rc"); | |
96 | if (fp != NULL) | |
97 | { | |
98 | /* No threads use this stream. */ | |
99 | __fsetlocking (fp, FSETLOCKING_BYCALLER); | |
100 | GET_NPROCS_PARSER (fp, buffer, result); | |
101 | fclose (fp); | |
102 | } | |
103 | } | |
104 | ||
105 | return result; | |
106 | } | |
845dcb57 UD |
107 | weak_alias (__get_nprocs, get_nprocs) |
108 | ||
bdb04ee8 | 109 | |
bdb04ee8 UD |
110 | /* On some architectures it is possible to distinguish between configured |
111 | and active cpus. */ | |
112 | int | |
113 | __get_nprocs_conf () | |
114 | { | |
bdb04ee8 UD |
115 | /* XXX Here will come a test for the new system call. */ |
116 | ||
9506149a UD |
117 | /* Try to use the sysfs filesystem. It has actual information about |
118 | online processors. */ | |
119 | DIR *dir = __opendir ("/sys/devices/system/cpu"); | |
120 | if (dir != NULL) | |
121 | { | |
122 | int count = 0; | |
123 | struct dirent64 *d; | |
124 | ||
125 | while ((d = __readdir64 (dir)) != NULL) | |
126 | /* NB: the sysfs has d_type support. */ | |
127 | if (d->d_type == DT_DIR && strncmp (d->d_name, "cpu", 3) == 0) | |
128 | { | |
129 | char *endp; | |
130 | unsigned long int nr = strtoul (d->d_name + 3, &endp, 10); | |
131 | if (nr != ULONG_MAX && endp != d->d_name + 3 && *endp == '\0') | |
132 | ++count; | |
133 | } | |
134 | ||
135 | __closedir (dir); | |
136 | ||
137 | return count; | |
138 | } | |
139 | ||
140 | int result = 1; | |
141 | ||
142 | #ifdef GET_NPROCS_CONF_PARSER | |
bdb04ee8 | 143 | /* If we haven't found an appropriate entry return 1. */ |
5c980df9 UD |
144 | FILE *fp = fopen ("/proc/cpuinfo", "rc"); |
145 | if (fp != NULL) | |
bdb04ee8 | 146 | { |
9506149a UD |
147 | char buffer[8192]; |
148 | ||
5c980df9 UD |
149 | /* No threads use this stream. */ |
150 | __fsetlocking (fp, FSETLOCKING_BYCALLER); | |
151 | GET_NPROCS_CONF_PARSER (fp, buffer, result); | |
152 | fclose (fp); | |
bdb04ee8 | 153 | } |
9506149a | 154 | #else |
0abf17de | 155 | result = __get_nprocs (); |
9506149a | 156 | #endif |
bdb04ee8 UD |
157 | |
158 | return result; | |
159 | } | |
bdb04ee8 | 160 | weak_alias (__get_nprocs_conf, get_nprocs_conf) |
845dcb57 UD |
161 | |
162 | /* General function to get information about memory status from proc | |
163 | filesystem. */ | |
e4cf5229 | 164 | static long int |
dfd2257a | 165 | internal_function |
845dcb57 UD |
166 | phys_pages_info (const char *format) |
167 | { | |
845dcb57 | 168 | char buffer[8192]; |
e4cf5229 | 169 | long int result = -1; |
845dcb57 | 170 | |
845dcb57 | 171 | /* If we haven't found an appropriate entry return 1. */ |
5c980df9 UD |
172 | FILE *fp = fopen ("/proc/meminfo", "rc"); |
173 | if (fp != NULL) | |
845dcb57 | 174 | { |
5c980df9 UD |
175 | /* No threads use this stream. */ |
176 | __fsetlocking (fp, FSETLOCKING_BYCALLER); | |
177 | ||
178 | result = 0; | |
179 | /* Read all lines and count the lines starting with the | |
180 | string "processor". We don't have to fear extremely long | |
181 | lines since the kernel will not generate them. 8192 | |
182 | bytes are really enough. */ | |
183 | while (fgets_unlocked (buffer, sizeof buffer, fp) != NULL) | |
184 | if (sscanf (buffer, format, &result) == 1) | |
185 | { | |
186 | result /= (__getpagesize () / 1024); | |
187 | break; | |
188 | } | |
a334319f | 189 | |
5c980df9 | 190 | fclose (fp); |
845dcb57 UD |
191 | } |
192 | ||
193 | if (result == -1) | |
194 | /* We cannot get the needed value: signal an error. */ | |
c4029823 | 195 | __set_errno (ENOSYS); |
845dcb57 UD |
196 | |
197 | return result; | |
198 | } | |
199 | ||
200 | ||
201 | /* Return the number of pages of physical memory in the system. There | |
202 | is currently (as of version 2.0.21) no system call to determine the | |
203 | number. It is planned for the 2.1.x series to add this, though. | |
204 | ||
205 | One possibility to implement it for systems using Linux 2.0 is to | |
206 | examine the pseudo file /proc/cpuinfo. Here we have one entry for | |
207 | each processor. | |
208 | ||
209 | But not all systems have support for the /proc filesystem. If it | |
210 | is not available we return -1 as an error signal. */ | |
e4cf5229 | 211 | long int |
845dcb57 UD |
212 | __get_phys_pages () |
213 | { | |
214 | /* XXX Here will come a test for the new system call. */ | |
215 | ||
e4cf5229 | 216 | return phys_pages_info ("MemTotal: %ld kB"); |
845dcb57 UD |
217 | } |
218 | weak_alias (__get_phys_pages, get_phys_pages) | |
219 | ||
220 | ||
221 | /* Return the number of available pages of physical memory in the | |
222 | system. There is currently (as of version 2.0.21) no system call | |
223 | to determine the number. It is planned for the 2.1.x series to add | |
224 | this, though. | |
225 | ||
226 | One possibility to implement it for systems using Linux 2.0 is to | |
227 | examine the pseudo file /proc/cpuinfo. Here we have one entry for | |
228 | each processor. | |
229 | ||
230 | But not all systems have support for the /proc filesystem. If it | |
231 | is not available we return -1 as an error signal. */ | |
e4cf5229 | 232 | long int |
845dcb57 UD |
233 | __get_avphys_pages () |
234 | { | |
235 | /* XXX Here will come a test for the new system call. */ | |
236 | ||
e4cf5229 | 237 | return phys_pages_info ("MemFree: %ld kB"); |
845dcb57 UD |
238 | } |
239 | weak_alias (__get_avphys_pages, get_avphys_pages) |