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 3 of the License, or
9 (at your option) any later version.
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, see <http://www.gnu.org/licenses/>. */
19 /* Written by Paul Eggert. */
24 # include <sys/pstat.h>
28 # include <sys/sysmp.h>
31 #if HAVE_SYS_SYSINFO_H && HAVE_MACHINE_HAL_SYSINFO_H
32 # include <sys/sysinfo.h>
33 # include <machine/hal_sysinfo.h>
37 # include <sys/table.h>
40 #include <sys/types.h>
43 # include <sys/param.h>
47 # include <sys/sysctl.h>
50 #if HAVE_SYS_SYSTEMCFG_H
51 # include <sys/systemcfg.h>
55 # define WIN32_LEAN_AND_MEAN
57 /* MEMORYSTATUSEX is missing from older windows headers, so define
58 a local replacement. */
63 DWORDLONG ullTotalPhys
;
64 DWORDLONG ullAvailPhys
;
65 DWORDLONG ullTotalPageFile
;
66 DWORDLONG ullAvailPageFile
;
67 DWORDLONG ullTotalVirtual
;
68 DWORDLONG ullAvailVirtual
;
69 DWORDLONG ullAvailExtendedVirtual
;
71 typedef WINBOOL (WINAPI
*PFN_MS_EX
) (lMEMORYSTATUSEX
*);
74 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
76 /* Return the total amount of physical memory. */
80 #if defined _SC_PHYS_PAGES && defined _SC_PAGESIZE
81 { /* This works on linux-gnu, solaris2 and cygwin. */
82 double pages
= sysconf (_SC_PHYS_PAGES
);
83 double pagesize
= sysconf (_SC_PAGESIZE
);
84 if (0 <= pages
&& 0 <= pagesize
)
85 return pages
* pagesize
;
89 #if HAVE_PSTAT_GETSTATIC
90 { /* This works on hpux11. */
91 struct pst_static pss
;
92 if (0 <= pstat_getstatic (&pss
, sizeof pss
, 1, 0))
94 double pages
= pss
.physical_memory
;
95 double pagesize
= pss
.page_size
;
96 if (0 <= pages
&& 0 <= pagesize
)
97 return pages
* pagesize
;
102 #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
103 { /* This works on irix6. */
104 struct rminfo realmem
;
105 if (sysmp (MP_SAGET
, MPSA_RMINFO
, &realmem
, sizeof realmem
) == 0)
107 double pagesize
= sysconf (_SC_PAGESIZE
);
108 double pages
= realmem
.physmem
;
109 if (0 <= pages
&& 0 <= pagesize
)
110 return pages
* pagesize
;
115 #if HAVE_GETSYSINFO && defined GSI_PHYSMEM
116 { /* This works on Tru64 UNIX V4/5. */
119 if (getsysinfo (GSI_PHYSMEM
, (caddr_t
) &physmem
, sizeof (physmem
),
120 NULL
, NULL
, NULL
) == 1)
122 double kbytes
= physmem
;
125 return kbytes
* 1024.0;
130 #if HAVE_SYSCTL && defined HW_PHYSMEM
131 { /* This works on *bsd and darwin. */
132 unsigned int physmem
;
133 size_t len
= sizeof physmem
;
134 static int mib
[2] = { CTL_HW
, HW_PHYSMEM
};
136 if (sysctl (mib
, ARRAY_SIZE (mib
), &physmem
, &len
, NULL
, 0) == 0
137 && len
== sizeof (physmem
))
138 return (double) physmem
;
142 #if HAVE__SYSTEM_CONFIGURATION
143 /* This works on AIX. */
144 return _system_configuration
.physmem
;
148 { /* this works on windows */
150 HMODULE h
= GetModuleHandle ("kernel32.dll");
155 /* Use GlobalMemoryStatusEx if available. */
156 if ((pfnex
= (PFN_MS_EX
) GetProcAddress (h
, "GlobalMemoryStatusEx")))
158 lMEMORYSTATUSEX lms_ex
;
159 lms_ex
.dwLength
= sizeof lms_ex
;
160 if (!pfnex (&lms_ex
))
162 return (double) lms_ex
.ullTotalPhys
;
165 /* Fall back to GlobalMemoryStatus which is always available.
166 but returns wrong results for physical memory > 4GB. */
170 GlobalMemoryStatus (&ms
);
171 return (double) ms
.dwTotalPhys
;
176 /* Guess 64 MB. It's probably an older host, so guess small. */
177 return 64 * 1024 * 1024;
180 /* Return the amount of physical memory available. */
182 physmem_available (void)
184 #if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE
185 { /* This works on linux-gnu, solaris2 and cygwin. */
186 double pages
= sysconf (_SC_AVPHYS_PAGES
);
187 double pagesize
= sysconf (_SC_PAGESIZE
);
188 if (0 <= pages
&& 0 <= pagesize
)
189 return pages
* pagesize
;
193 #if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC
194 { /* This works on hpux11. */
195 struct pst_static pss
;
196 struct pst_dynamic psd
;
197 if (0 <= pstat_getstatic (&pss
, sizeof pss
, 1, 0)
198 && 0 <= pstat_getdynamic (&psd
, sizeof psd
, 1, 0))
200 double pages
= psd
.psd_free
;
201 double pagesize
= pss
.page_size
;
202 if (0 <= pages
&& 0 <= pagesize
)
203 return pages
* pagesize
;
208 #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
209 { /* This works on irix6. */
210 struct rminfo realmem
;
211 if (sysmp (MP_SAGET
, MPSA_RMINFO
, &realmem
, sizeof realmem
) == 0)
213 double pagesize
= sysconf (_SC_PAGESIZE
);
214 double pages
= realmem
.availrmem
;
215 if (0 <= pages
&& 0 <= pagesize
)
216 return pages
* pagesize
;
221 #if HAVE_TABLE && defined TBL_VMSTATS
222 { /* This works on Tru64 UNIX V4/5. */
223 struct tbl_vmstats vmstats
;
225 if (table (TBL_VMSTATS
, 0, &vmstats
, 1, sizeof (vmstats
)) == 1)
227 double pages
= vmstats
.free_count
;
228 double pagesize
= vmstats
.pagesize
;
230 if (0 <= pages
&& 0 <= pagesize
)
231 return pages
* pagesize
;
236 #if HAVE_SYSCTL && defined HW_USERMEM
237 { /* This works on *bsd and darwin. */
238 unsigned int usermem
;
239 size_t len
= sizeof usermem
;
240 static int mib
[2] = { CTL_HW
, HW_USERMEM
};
242 if (sysctl (mib
, ARRAY_SIZE (mib
), &usermem
, &len
, NULL
, 0) == 0
243 && len
== sizeof (usermem
))
244 return (double) usermem
;
249 { /* this works on windows */
251 HMODULE h
= GetModuleHandle ("kernel32.dll");
256 /* Use GlobalMemoryStatusEx if available. */
257 if ((pfnex
= (PFN_MS_EX
) GetProcAddress (h
, "GlobalMemoryStatusEx")))
259 lMEMORYSTATUSEX lms_ex
;
260 lms_ex
.dwLength
= sizeof lms_ex
;
261 if (!pfnex (&lms_ex
))
263 return (double) lms_ex
.ullAvailPhys
;
266 /* Fall back to GlobalMemoryStatus which is always available.
267 but returns wrong results for physical memory > 4GB */
271 GlobalMemoryStatus (&ms
);
272 return (double) ms
.dwAvailPhys
;
277 /* Guess 25% of physical memory. */
278 return physmem_total () / 4;
290 printf ("%12.f %12.f\n", physmem_total (), physmem_available ());
298 compile-command: "gcc -DDEBUG -g -O -Wall -W physmem.c"