]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/getsysstats.c
* sysdeps/unix/sysv/linux/sh/lowlevellock.S: Define
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / getsysstats.c
CommitLineData
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
71int
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
107weak_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. */
112int
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 160weak_alias (__get_nprocs_conf, get_nprocs_conf)
845dcb57
UD
161
162/* General function to get information about memory status from proc
163 filesystem. */
e4cf5229 164static long int
dfd2257a 165internal_function
845dcb57
UD
166phys_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 211long 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}
218weak_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 232long 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}
239weak_alias (__get_avphys_pages, get_avphys_pages)