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