1 /* Calculate the size of physical memory.
3 Copyright (C) 2000, 2001, 2003, 2005, 2006 Free Software
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
20 /* Written by Paul Eggert. */
25 # include <sys/pstat.h>
29 # include <sys/sysmp.h>
32 #if HAVE_SYS_SYSINFO_H && HAVE_MACHINE_HAL_SYSINFO_H
33 # include <sys/sysinfo.h>
34 # include <machine/hal_sysinfo.h>
38 # include <sys/table.h>
41 #include <sys/types.h>
44 # include <sys/param.h>
48 # include <sys/sysctl.h>
51 #if HAVE_SYS_SYSTEMCFG_H
52 # include <sys/systemcfg.h>
56 # define WIN32_LEAN_AND_MEAN
58 /* MEMORYSTATUSEX is missing from older windows headers, so define
59 a local replacement. */
64 DWORDLONG ullTotalPhys
;
65 DWORDLONG ullAvailPhys
;
66 DWORDLONG ullTotalPageFile
;
67 DWORDLONG ullAvailPageFile
;
68 DWORDLONG ullTotalVirtual
;
69 DWORDLONG ullAvailVirtual
;
70 DWORDLONG ullAvailExtendedVirtual
;
72 typedef WINBOOL (WINAPI
*PFN_MS_EX
) (lMEMORYSTATUSEX
*);
75 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
77 /* Return the total amount of physical memory. */
81 #if defined _SC_PHYS_PAGES && defined _SC_PAGESIZE
82 { /* This works on linux-gnu, solaris2 and cygwin. */
83 double pages
= sysconf (_SC_PHYS_PAGES
);
84 double pagesize
= sysconf (_SC_PAGESIZE
);
85 if (0 <= pages
&& 0 <= pagesize
)
86 return pages
* pagesize
;
90 #if HAVE_PSTAT_GETSTATIC
91 { /* This works on hpux11. */
92 struct pst_static pss
;
93 if (0 <= pstat_getstatic (&pss
, sizeof pss
, 1, 0))
95 double pages
= pss
.physical_memory
;
96 double pagesize
= pss
.page_size
;
97 if (0 <= pages
&& 0 <= pagesize
)
98 return pages
* pagesize
;
103 #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
104 { /* This works on irix6. */
105 struct rminfo realmem
;
106 if (sysmp (MP_SAGET
, MPSA_RMINFO
, &realmem
, sizeof realmem
) == 0)
108 double pagesize
= sysconf (_SC_PAGESIZE
);
109 double pages
= realmem
.physmem
;
110 if (0 <= pages
&& 0 <= pagesize
)
111 return pages
* pagesize
;
116 #if HAVE_GETSYSINFO && defined GSI_PHYSMEM
117 { /* This works on Tru64 UNIX V4/5. */
120 if (getsysinfo (GSI_PHYSMEM
, (caddr_t
) &physmem
, sizeof (physmem
),
121 NULL
, NULL
, NULL
) == 1)
123 double kbytes
= physmem
;
126 return kbytes
* 1024.0;
131 #if HAVE_SYSCTL && defined HW_PHYSMEM
132 { /* This works on *bsd and darwin. */
133 unsigned int physmem
;
134 size_t len
= sizeof physmem
;
135 static int mib
[2] = { CTL_HW
, HW_PHYSMEM
};
137 if (sysctl (mib
, ARRAY_SIZE (mib
), &physmem
, &len
, NULL
, 0) == 0
138 && len
== sizeof (physmem
))
139 return (double) physmem
;
143 #if HAVE__SYSTEM_CONFIGURATION
144 /* This works on AIX. */
145 return _system_configuration
.physmem
;
149 { /* this works on windows */
151 HMODULE h
= GetModuleHandle ("kernel32.dll");
156 /* Use GlobalMemoryStatusEx if available. */
157 if ((pfnex
= (PFN_MS_EX
) GetProcAddress (h
, "GlobalMemoryStatusEx")))
159 lMEMORYSTATUSEX lms_ex
;
160 lms_ex
.dwLength
= sizeof lms_ex
;
161 if (!pfnex (&lms_ex
))
163 return (double) lms_ex
.ullTotalPhys
;
166 /* Fall back to GlobalMemoryStatus which is always available.
167 but returns wrong results for physical memory > 4GB. */
171 GlobalMemoryStatus (&ms
);
172 return (double) ms
.dwTotalPhys
;
177 /* Guess 64 MB. It's probably an older host, so guess small. */
178 return 64 * 1024 * 1024;
181 /* Return the amount of physical memory available. */
183 physmem_available (void)
185 #if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE
186 { /* This works on linux-gnu, solaris2 and cygwin. */
187 double pages
= sysconf (_SC_AVPHYS_PAGES
);
188 double pagesize
= sysconf (_SC_PAGESIZE
);
189 if (0 <= pages
&& 0 <= pagesize
)
190 return pages
* pagesize
;
194 #if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC
195 { /* This works on hpux11. */
196 struct pst_static pss
;
197 struct pst_dynamic psd
;
198 if (0 <= pstat_getstatic (&pss
, sizeof pss
, 1, 0)
199 && 0 <= pstat_getdynamic (&psd
, sizeof psd
, 1, 0))
201 double pages
= psd
.psd_free
;
202 double pagesize
= pss
.page_size
;
203 if (0 <= pages
&& 0 <= pagesize
)
204 return pages
* pagesize
;
209 #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
210 { /* This works on irix6. */
211 struct rminfo realmem
;
212 if (sysmp (MP_SAGET
, MPSA_RMINFO
, &realmem
, sizeof realmem
) == 0)
214 double pagesize
= sysconf (_SC_PAGESIZE
);
215 double pages
= realmem
.availrmem
;
216 if (0 <= pages
&& 0 <= pagesize
)
217 return pages
* pagesize
;
222 #if HAVE_TABLE && defined TBL_VMSTATS
223 { /* This works on Tru64 UNIX V4/5. */
224 struct tbl_vmstats vmstats
;
226 if (table (TBL_VMSTATS
, 0, &vmstats
, 1, sizeof (vmstats
)) == 1)
228 double pages
= vmstats
.free_count
;
229 double pagesize
= vmstats
.pagesize
;
231 if (0 <= pages
&& 0 <= pagesize
)
232 return pages
* pagesize
;
237 #if HAVE_SYSCTL && defined HW_USERMEM
238 { /* This works on *bsd and darwin. */
239 unsigned int usermem
;
240 size_t len
= sizeof usermem
;
241 static int mib
[2] = { CTL_HW
, HW_USERMEM
};
243 if (sysctl (mib
, ARRAY_SIZE (mib
), &usermem
, &len
, NULL
, 0) == 0
244 && len
== sizeof (usermem
))
245 return (double) usermem
;
250 { /* this works on windows */
252 HMODULE h
= GetModuleHandle ("kernel32.dll");
257 /* Use GlobalMemoryStatusEx if available. */
258 if ((pfnex
= (PFN_MS_EX
) GetProcAddress (h
, "GlobalMemoryStatusEx")))
260 lMEMORYSTATUSEX lms_ex
;
261 lms_ex
.dwLength
= sizeof lms_ex
;
262 if (!pfnex (&lms_ex
))
264 return (double) lms_ex
.ullAvailPhys
;
267 /* Fall back to GlobalMemoryStatus which is always available.
268 but returns wrong results for physical memory > 4GB */
272 GlobalMemoryStatus (&ms
);
273 return (double) ms
.dwAvailPhys
;
278 /* Guess 25% of physical memory. */
279 return physmem_total () / 4;
291 printf ("%12.f %12.f\n", physmem_total (), physmem_available ());
299 compile-command: "gcc -DDEBUG -g -O -Wall -W physmem.c"