xref: /dflybsd-src/contrib/gcc-4.7/libiberty/physmem.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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