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