xref: /dflybsd-src/contrib/gcc-8.0/libiberty/physmem.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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