physmem.c revision 261188
1/* Calculate the size of physical memory. 2 Copyright 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc. 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 17 18/* Written by Paul Eggert. */ 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 32#if HAVE_SYS_SYSMP_H 33# include <sys/sysmp.h> 34#endif 35 36#if HAVE_SYS_SYSINFO_H && HAVE_MACHINE_HAL_SYSINFO_H 37# include <sys/sysinfo.h> 38# include <machine/hal_sysinfo.h> 39#endif 40 41#if HAVE_SYS_TABLE_H 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> 57#endif 58 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. */ 64typedef struct 65{ 66 DWORD dwLength; 67 DWORD dwMemoryLoad; 68 DWORDLONG ullTotalPhys; 69 DWORDLONG ullAvailPhys; 70 DWORDLONG ullTotalPageFile; 71 DWORDLONG ullAvailPageFile; 72 DWORDLONG ullTotalVirtual; 73 DWORDLONG ullAvailVirtual; 74 DWORDLONG ullAvailExtendedVirtual; 75} lMEMORYSTATUSEX; 76typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*); 77#endif 78 79#include "libiberty.h" 80 81/* Return the total amount of physical memory. */ 82double 83physmem_total (void) 84{ 85#if defined _SC_PHYS_PAGES && defined _SC_PAGESIZE 86 { /* This works on linux-gnu, solaris2 and cygwin. */ 87 double pages = sysconf (_SC_PHYS_PAGES); 88 double pagesize = sysconf (_SC_PAGESIZE); 89 if (0 <= pages && 0 <= pagesize) 90 return pages * pagesize; 91 } 92#endif 93 94#if HAVE_PSTAT_GETSTATIC 95 { /* This works on hpux11. */ 96 struct pst_static pss; 97 if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0)) 98 { 99 double pages = pss.physical_memory; 100 double pagesize = pss.page_size; 101 if (0 <= pages && 0 <= pagesize) 102 return pages * pagesize; 103 } 104 } 105#endif 106 107#if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE 108 { /* This works on irix6. */ 109 struct rminfo realmem; 110 if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0) 111 { 112 double pagesize = sysconf (_SC_PAGESIZE); 113 double pages = realmem.physmem; 114 if (0 <= pages && 0 <= pagesize) 115 return pages * pagesize; 116 } 117 } 118#endif 119 120#if HAVE_GETSYSINFO && defined GSI_PHYSMEM 121 { /* This works on Tru64 UNIX V4/5. */ 122 int physmem; 123 124 if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem), 125 NULL, NULL, NULL) == 1) 126 { 127 double kbytes = physmem; 128 129 if (0 <= kbytes) 130 return kbytes * 1024.0; 131 } 132 } 133#endif 134 135#if HAVE_SYSCTL && defined HW_PHYSMEM 136 { /* This works on *bsd and darwin. */ 137 unsigned int physmem; 138 size_t len = sizeof physmem; 139 static int mib[2] = { CTL_HW, HW_PHYSMEM }; 140 141 if (sysctl (mib, ARRAY_SIZE (mib), &physmem, &len, NULL, 0) == 0 142 && len == sizeof (physmem)) 143 return (double) physmem; 144 } 145#endif 146 147#if HAVE__SYSTEM_CONFIGURATION 148 /* This works on AIX 4.3.3+. */ 149 return _system_configuration.physmem; 150#endif 151 152#if defined _WIN32 153 { /* this works on windows */ 154 PFN_MS_EX pfnex; 155 HMODULE h = GetModuleHandle ("kernel32.dll"); 156 157 if (!h) 158 return 0.0; 159 160 /* Use GlobalMemoryStatusEx if available. */ 161 if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx"))) 162 { 163 lMEMORYSTATUSEX lms_ex; 164 lms_ex.dwLength = sizeof lms_ex; 165 if (!pfnex (&lms_ex)) 166 return 0.0; 167 return (double) lms_ex.ullTotalPhys; 168 } 169 170 /* Fall back to GlobalMemoryStatus which is always available. 171 but returns wrong results for physical memory > 4GB. */ 172 else 173 { 174 MEMORYSTATUS ms; 175 GlobalMemoryStatus (&ms); 176 return (double) ms.dwTotalPhys; 177 } 178 } 179#endif 180 181 /* Return 0 if we can't determine the value. */ 182 return 0; 183} 184 185/* APPLE LOCAL begin retune gc params 6124839 */ 186unsigned int 187ncpu_available (void) 188{ 189#if HAVE_SYSCTL && defined HW_AVAILCPU 190 { /* This works on *bsd and darwin. */ 191 unsigned int ncpu; 192 size_t len = sizeof ncpu; 193 static int mib[2] = { CTL_HW, HW_AVAILCPU }; 194 195 if (sysctl (mib, ARRAY_SIZE (mib), &ncpu, &len, NULL, 0) == 0 196 && len == sizeof (ncpu)) 197 return ncpu; 198 } 199#endif 200#if HAVE_SYSCTL && defined HW_NCPU 201 { /* This works on *bsd and darwin. */ 202 unsigned int ncpu; 203 size_t len = sizeof ncpu; 204 static int mib[2] = { CTL_HW, HW_NCPU }; 205 206 if (sysctl (mib, ARRAY_SIZE (mib), &ncpu, &len, NULL, 0) == 0 207 && len == sizeof (ncpu)) 208 return ncpu; 209 } 210#endif 211 return 1; 212} 213/* APPLE LOCAL end retune gc params 6124839 */ 214 215/* Return the amount of physical memory available. */ 216double 217physmem_available (void) 218{ 219#if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE 220 { /* This works on linux-gnu, solaris2 and cygwin. */ 221 double pages = sysconf (_SC_AVPHYS_PAGES); 222 double pagesize = sysconf (_SC_PAGESIZE); 223 if (0 <= pages && 0 <= pagesize) 224 return pages * pagesize; 225 } 226#endif 227 228#if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC 229 { /* This works on hpux11. */ 230 struct pst_static pss; 231 struct pst_dynamic psd; 232 if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0) 233 && 0 <= pstat_getdynamic (&psd, sizeof psd, 1, 0)) 234 { 235 double pages = psd.psd_free; 236 double pagesize = pss.page_size; 237 if (0 <= pages && 0 <= pagesize) 238 return pages * pagesize; 239 } 240 } 241#endif 242 243#if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE 244 { /* This works on irix6. */ 245 struct rminfo realmem; 246 if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0) 247 { 248 double pagesize = sysconf (_SC_PAGESIZE); 249 double pages = realmem.availrmem; 250 if (0 <= pages && 0 <= pagesize) 251 return pages * pagesize; 252 } 253 } 254#endif 255 256#if HAVE_TABLE && defined TBL_VMSTATS 257 { /* This works on Tru64 UNIX V4/5. */ 258 struct tbl_vmstats vmstats; 259 260 if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1) 261 { 262 double pages = vmstats.free_count; 263 double pagesize = vmstats.pagesize; 264 265 if (0 <= pages && 0 <= pagesize) 266 return pages * pagesize; 267 } 268 } 269#endif 270 271#if HAVE_SYSCTL && defined HW_USERMEM 272 { /* This works on *bsd and darwin. */ 273 unsigned int usermem; 274 size_t len = sizeof usermem; 275 static int mib[2] = { CTL_HW, HW_USERMEM }; 276 277 if (sysctl (mib, ARRAY_SIZE (mib), &usermem, &len, NULL, 0) == 0 278 && len == sizeof (usermem)) 279 return (double) usermem; 280 } 281#endif 282 283#if defined _WIN32 284 { /* this works on windows */ 285 PFN_MS_EX pfnex; 286 HMODULE h = GetModuleHandle ("kernel32.dll"); 287 288 if (!h) 289 return 0.0; 290 291 /* Use GlobalMemoryStatusEx if available. */ 292 if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx"))) 293 { 294 lMEMORYSTATUSEX lms_ex; 295 lms_ex.dwLength = sizeof lms_ex; 296 if (!pfnex (&lms_ex)) 297 return 0.0; 298 return (double) lms_ex.ullAvailPhys; 299 } 300 301 /* Fall back to GlobalMemoryStatus which is always available. 302 but returns wrong results for physical memory > 4GB */ 303 else 304 { 305 MEMORYSTATUS ms; 306 GlobalMemoryStatus (&ms); 307 return (double) ms.dwAvailPhys; 308 } 309 } 310#endif 311 312 /* Guess 25% of physical memory. */ 313 return physmem_total () / 4; 314} 315 316 317#if DEBUG 318 319# include <stdio.h> 320# include <stdlib.h> 321 322int 323main (void) 324{ 325 printf ("%12.f %12.f\n", physmem_total (), physmem_available ()); 326 exit (0); 327} 328 329#endif /* DEBUG */ 330 331/* 332Local Variables: 333compile-command: "gcc -DDEBUG -DHAVE_CONFIG_H -I.. -g -O -Wall -W physmem.c" 334End: 335*/ 336