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