physmem.c revision 1.1 1 1.1 christos /* Calculate the size of physical memory.
2 1.1 christos Copyright 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos This program is free software; you can redistribute it and/or modify
5 1.1 christos it under the terms of the GNU General Public License as published by
6 1.1 christos the Free Software Foundation; either version 2, or (at your option)
7 1.1 christos any later version.
8 1.1 christos
9 1.1 christos This program is distributed in the hope that it will be useful,
10 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
11 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 1.1 christos GNU General Public License for more details.
13 1.1 christos
14 1.1 christos You should have received a copy of the GNU General Public License
15 1.1 christos along with this program; if not, write to the Free Software Foundation,
16 1.1 christos Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
17 1.1 christos
18 1.1 christos /* Written by Paul Eggert. */
19 1.1 christos
20 1.1 christos #if HAVE_CONFIG_H
21 1.1 christos # include <config.h>
22 1.1 christos #endif
23 1.1 christos
24 1.1 christos #if HAVE_UNISTD_H
25 1.1 christos # include <unistd.h>
26 1.1 christos #endif
27 1.1 christos
28 1.1 christos #if HAVE_SYS_PSTAT_H
29 1.1 christos # include <sys/pstat.h>
30 1.1 christos #endif
31 1.1 christos
32 1.1 christos #if HAVE_SYS_SYSMP_H
33 1.1 christos # include <sys/sysmp.h>
34 1.1 christos #endif
35 1.1 christos
36 1.1 christos #if HAVE_SYS_SYSINFO_H && HAVE_MACHINE_HAL_SYSINFO_H
37 1.1 christos # include <sys/sysinfo.h>
38 1.1 christos # include <machine/hal_sysinfo.h>
39 1.1 christos #endif
40 1.1 christos
41 1.1 christos #if HAVE_SYS_TABLE_H
42 1.1 christos # include <sys/table.h>
43 1.1 christos #endif
44 1.1 christos
45 1.1 christos #include <sys/types.h>
46 1.1 christos
47 1.1 christos #if HAVE_SYS_PARAM_H
48 1.1 christos # include <sys/param.h>
49 1.1 christos #endif
50 1.1 christos
51 1.1 christos #if HAVE_SYS_SYSCTL_H
52 1.1 christos # include <sys/sysctl.h>
53 1.1 christos #endif
54 1.1 christos
55 1.1 christos #if HAVE_SYS_SYSTEMCFG_H
56 1.1 christos # include <sys/systemcfg.h>
57 1.1 christos #endif
58 1.1 christos
59 1.1 christos #ifdef _WIN32
60 1.1 christos # define WIN32_LEAN_AND_MEAN
61 1.1 christos # include <windows.h>
62 1.1 christos /* MEMORYSTATUSEX is missing from older windows headers, so define
63 1.1 christos a local replacement. */
64 1.1 christos typedef struct
65 1.1 christos {
66 1.1 christos DWORD dwLength;
67 1.1 christos DWORD dwMemoryLoad;
68 1.1 christos DWORDLONG ullTotalPhys;
69 1.1 christos DWORDLONG ullAvailPhys;
70 1.1 christos DWORDLONG ullTotalPageFile;
71 1.1 christos DWORDLONG ullAvailPageFile;
72 1.1 christos DWORDLONG ullTotalVirtual;
73 1.1 christos DWORDLONG ullAvailVirtual;
74 1.1 christos DWORDLONG ullAvailExtendedVirtual;
75 1.1 christos } lMEMORYSTATUSEX;
76 1.1 christos typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*);
77 1.1 christos #endif
78 1.1 christos
79 1.1 christos #include "libiberty.h"
80 1.1 christos
81 1.1 christos /* Return the total amount of physical memory. */
82 1.1 christos double
83 1.1 christos physmem_total (void)
84 1.1 christos {
85 1.1 christos #if defined _SC_PHYS_PAGES && defined _SC_PAGESIZE
86 1.1 christos { /* This works on linux-gnu, solaris2 and cygwin. */
87 1.1 christos double pages = sysconf (_SC_PHYS_PAGES);
88 1.1 christos double pagesize = sysconf (_SC_PAGESIZE);
89 1.1 christos if (0 <= pages && 0 <= pagesize)
90 1.1 christos return pages * pagesize;
91 1.1 christos }
92 1.1 christos #endif
93 1.1 christos
94 1.1 christos #if HAVE_PSTAT_GETSTATIC
95 1.1 christos { /* This works on hpux11. */
96 1.1 christos struct pst_static pss;
97 1.1 christos if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0))
98 1.1 christos {
99 1.1 christos double pages = pss.physical_memory;
100 1.1 christos double pagesize = pss.page_size;
101 1.1 christos if (0 <= pages && 0 <= pagesize)
102 1.1 christos return pages * pagesize;
103 1.1 christos }
104 1.1 christos }
105 1.1 christos #endif
106 1.1 christos
107 1.1 christos #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
108 1.1 christos { /* This works on irix6. */
109 1.1 christos struct rminfo realmem;
110 1.1 christos if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0)
111 1.1 christos {
112 1.1 christos double pagesize = sysconf (_SC_PAGESIZE);
113 1.1 christos double pages = realmem.physmem;
114 1.1 christos if (0 <= pages && 0 <= pagesize)
115 1.1 christos return pages * pagesize;
116 1.1 christos }
117 1.1 christos }
118 1.1 christos #endif
119 1.1 christos
120 1.1 christos #if HAVE_GETSYSINFO && defined GSI_PHYSMEM
121 1.1 christos { /* This works on Tru64 UNIX V4/5. */
122 1.1 christos int physmem;
123 1.1 christos
124 1.1 christos if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem),
125 1.1 christos NULL, NULL, NULL) == 1)
126 1.1 christos {
127 1.1 christos double kbytes = physmem;
128 1.1 christos
129 1.1 christos if (0 <= kbytes)
130 1.1 christos return kbytes * 1024.0;
131 1.1 christos }
132 1.1 christos }
133 1.1 christos #endif
134 1.1 christos
135 1.1 christos #if HAVE_SYSCTL && defined HW_PHYSMEM
136 1.1 christos { /* This works on *bsd and darwin. */
137 1.1 christos unsigned int physmem;
138 1.1 christos size_t len = sizeof physmem;
139 1.1 christos static int mib[2] = { CTL_HW, HW_PHYSMEM };
140 1.1 christos
141 1.1 christos if (sysctl (mib, ARRAY_SIZE (mib), &physmem, &len, NULL, 0) == 0
142 1.1 christos && len == sizeof (physmem))
143 1.1 christos return (double) physmem;
144 1.1 christos }
145 1.1 christos #endif
146 1.1 christos
147 1.1 christos #if HAVE__SYSTEM_CONFIGURATION
148 1.1 christos /* This works on AIX 4.3.3+. */
149 1.1 christos return _system_configuration.physmem;
150 1.1 christos #endif
151 1.1 christos
152 1.1 christos #if defined _WIN32
153 1.1 christos { /* this works on windows */
154 1.1 christos PFN_MS_EX pfnex;
155 1.1 christos HMODULE h = GetModuleHandle ("kernel32.dll");
156 1.1 christos
157 1.1 christos if (!h)
158 1.1 christos return 0.0;
159 1.1 christos
160 1.1 christos /* Use GlobalMemoryStatusEx if available. */
161 1.1 christos if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx")))
162 1.1 christos {
163 1.1 christos lMEMORYSTATUSEX lms_ex;
164 1.1 christos lms_ex.dwLength = sizeof lms_ex;
165 1.1 christos if (!pfnex (&lms_ex))
166 1.1 christos return 0.0;
167 1.1 christos return (double) lms_ex.ullTotalPhys;
168 1.1 christos }
169 1.1 christos
170 1.1 christos /* Fall back to GlobalMemoryStatus which is always available.
171 1.1 christos but returns wrong results for physical memory > 4GB. */
172 1.1 christos else
173 1.1 christos {
174 1.1 christos MEMORYSTATUS ms;
175 1.1 christos GlobalMemoryStatus (&ms);
176 1.1 christos return (double) ms.dwTotalPhys;
177 1.1 christos }
178 1.1 christos }
179 1.1 christos #endif
180 1.1 christos
181 1.1 christos /* Return 0 if we can't determine the value. */
182 1.1 christos return 0;
183 1.1 christos }
184 1.1 christos
185 1.1 christos /* Return the amount of physical memory available. */
186 1.1 christos double
187 1.1 christos physmem_available (void)
188 1.1 christos {
189 1.1 christos #if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE
190 1.1 christos { /* This works on linux-gnu, solaris2 and cygwin. */
191 1.1 christos double pages = sysconf (_SC_AVPHYS_PAGES);
192 1.1 christos double pagesize = sysconf (_SC_PAGESIZE);
193 1.1 christos if (0 <= pages && 0 <= pagesize)
194 1.1 christos return pages * pagesize;
195 1.1 christos }
196 1.1 christos #endif
197 1.1 christos
198 1.1 christos #if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC
199 1.1 christos { /* This works on hpux11. */
200 1.1 christos struct pst_static pss;
201 1.1 christos struct pst_dynamic psd;
202 1.1 christos if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0)
203 1.1 christos && 0 <= pstat_getdynamic (&psd, sizeof psd, 1, 0))
204 1.1 christos {
205 1.1 christos double pages = psd.psd_free;
206 1.1 christos double pagesize = pss.page_size;
207 1.1 christos if (0 <= pages && 0 <= pagesize)
208 1.1 christos return pages * pagesize;
209 1.1 christos }
210 1.1 christos }
211 1.1 christos #endif
212 1.1 christos
213 1.1 christos #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
214 1.1 christos { /* This works on irix6. */
215 1.1 christos struct rminfo realmem;
216 1.1 christos if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0)
217 1.1 christos {
218 1.1 christos double pagesize = sysconf (_SC_PAGESIZE);
219 1.1 christos double pages = realmem.availrmem;
220 1.1 christos if (0 <= pages && 0 <= pagesize)
221 1.1 christos return pages * pagesize;
222 1.1 christos }
223 1.1 christos }
224 1.1 christos #endif
225 1.1 christos
226 1.1 christos #if HAVE_TABLE && defined TBL_VMSTATS
227 1.1 christos { /* This works on Tru64 UNIX V4/5. */
228 1.1 christos struct tbl_vmstats vmstats;
229 1.1 christos
230 1.1 christos if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1)
231 1.1 christos {
232 1.1 christos double pages = vmstats.free_count;
233 1.1 christos double pagesize = vmstats.pagesize;
234 1.1 christos
235 1.1 christos if (0 <= pages && 0 <= pagesize)
236 1.1 christos return pages * pagesize;
237 1.1 christos }
238 1.1 christos }
239 1.1 christos #endif
240 1.1 christos
241 1.1 christos #if HAVE_SYSCTL && defined HW_USERMEM
242 1.1 christos { /* This works on *bsd and darwin. */
243 1.1 christos unsigned int usermem;
244 1.1 christos size_t len = sizeof usermem;
245 1.1 christos static int mib[2] = { CTL_HW, HW_USERMEM };
246 1.1 christos
247 1.1 christos if (sysctl (mib, ARRAY_SIZE (mib), &usermem, &len, NULL, 0) == 0
248 1.1 christos && len == sizeof (usermem))
249 1.1 christos return (double) usermem;
250 1.1 christos }
251 1.1 christos #endif
252 1.1 christos
253 1.1 christos #if defined _WIN32
254 1.1 christos { /* this works on windows */
255 1.1 christos PFN_MS_EX pfnex;
256 1.1 christos HMODULE h = GetModuleHandle ("kernel32.dll");
257 1.1 christos
258 1.1 christos if (!h)
259 1.1 christos return 0.0;
260 1.1 christos
261 1.1 christos /* Use GlobalMemoryStatusEx if available. */
262 1.1 christos if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx")))
263 1.1 christos {
264 1.1 christos lMEMORYSTATUSEX lms_ex;
265 1.1 christos lms_ex.dwLength = sizeof lms_ex;
266 1.1 christos if (!pfnex (&lms_ex))
267 1.1 christos return 0.0;
268 1.1 christos return (double) lms_ex.ullAvailPhys;
269 1.1 christos }
270 1.1 christos
271 1.1 christos /* Fall back to GlobalMemoryStatus which is always available.
272 1.1 christos but returns wrong results for physical memory > 4GB */
273 1.1 christos else
274 1.1 christos {
275 1.1 christos MEMORYSTATUS ms;
276 1.1 christos GlobalMemoryStatus (&ms);
277 1.1 christos return (double) ms.dwAvailPhys;
278 1.1 christos }
279 1.1 christos }
280 1.1 christos #endif
281 1.1 christos
282 1.1 christos /* Guess 25% of physical memory. */
283 1.1 christos return physmem_total () / 4;
284 1.1 christos }
285 1.1 christos
286 1.1 christos
287 1.1 christos #if DEBUG
288 1.1 christos
289 1.1 christos # include <stdio.h>
290 1.1 christos # include <stdlib.h>
291 1.1 christos
292 1.1 christos int
293 1.1 christos main (void)
294 1.1 christos {
295 1.1 christos printf ("%12.f %12.f\n", physmem_total (), physmem_available ());
296 1.1 christos exit (0);
297 1.1 christos }
298 1.1 christos
299 1.1 christos #endif /* DEBUG */
300 1.1 christos
301 1.1 christos /*
302 1.1 christos Local Variables:
303 1.1 christos compile-command: "gcc -DDEBUG -DHAVE_CONFIG_H -I.. -g -O -Wall -W physmem.c"
304 1.1 christos End:
305 1.1 christos */
306