1169695Skan/* Calculate the size of physical memory. 2169695Skan Copyright 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc. 3169695Skan 4169695Skan This program is free software; you can redistribute it and/or modify 5169695Skan it under the terms of the GNU General Public License as published by 6169695Skan the Free Software Foundation; either version 2, or (at your option) 7169695Skan any later version. 8169695Skan 9169695Skan This program is distributed in the hope that it will be useful, 10169695Skan but WITHOUT ANY WARRANTY; without even the implied warranty of 11169695Skan MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12169695Skan GNU General Public License for more details. 13169695Skan 14169695Skan You should have received a copy of the GNU General Public License 15169695Skan along with this program; if not, write to the Free Software Foundation, 16169695Skan Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 17169695Skan 18169695Skan/* Written by Paul Eggert. */ 19169695Skan 20169695Skan#if HAVE_CONFIG_H 21169695Skan# include <config.h> 22169695Skan#endif 23169695Skan 24169695Skan#if HAVE_UNISTD_H 25169695Skan# include <unistd.h> 26169695Skan#endif 27169695Skan 28169695Skan#if HAVE_SYS_PSTAT_H 29169695Skan# include <sys/pstat.h> 30169695Skan#endif 31169695Skan 32169695Skan#if HAVE_SYS_SYSMP_H 33169695Skan# include <sys/sysmp.h> 34169695Skan#endif 35169695Skan 36169695Skan#if HAVE_SYS_SYSINFO_H && HAVE_MACHINE_HAL_SYSINFO_H 37169695Skan# include <sys/sysinfo.h> 38169695Skan# include <machine/hal_sysinfo.h> 39169695Skan#endif 40169695Skan 41169695Skan#if HAVE_SYS_TABLE_H 42169695Skan# include <sys/table.h> 43169695Skan#endif 44169695Skan 45169695Skan#include <sys/types.h> 46169695Skan 47169695Skan#if HAVE_SYS_PARAM_H 48169695Skan# include <sys/param.h> 49169695Skan#endif 50169695Skan 51169695Skan#if HAVE_SYS_SYSCTL_H 52169695Skan# include <sys/sysctl.h> 53169695Skan#endif 54169695Skan 55169695Skan#if HAVE_SYS_SYSTEMCFG_H 56169695Skan# include <sys/systemcfg.h> 57169695Skan#endif 58169695Skan 59169695Skan#ifdef _WIN32 60169695Skan# define WIN32_LEAN_AND_MEAN 61169695Skan# include <windows.h> 62169695Skan/* MEMORYSTATUSEX is missing from older windows headers, so define 63169695Skan a local replacement. */ 64169695Skantypedef struct 65169695Skan{ 66169695Skan DWORD dwLength; 67169695Skan DWORD dwMemoryLoad; 68169695Skan DWORDLONG ullTotalPhys; 69169695Skan DWORDLONG ullAvailPhys; 70169695Skan DWORDLONG ullTotalPageFile; 71169695Skan DWORDLONG ullAvailPageFile; 72169695Skan DWORDLONG ullTotalVirtual; 73169695Skan DWORDLONG ullAvailVirtual; 74169695Skan DWORDLONG ullAvailExtendedVirtual; 75169695Skan} lMEMORYSTATUSEX; 76169695Skantypedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*); 77169695Skan#endif 78169695Skan 79169695Skan#include "libiberty.h" 80169695Skan 81169695Skan/* Return the total amount of physical memory. */ 82169695Skandouble 83169695Skanphysmem_total (void) 84169695Skan{ 85169695Skan#if defined _SC_PHYS_PAGES && defined _SC_PAGESIZE 86169695Skan { /* This works on linux-gnu, solaris2 and cygwin. */ 87169695Skan double pages = sysconf (_SC_PHYS_PAGES); 88169695Skan double pagesize = sysconf (_SC_PAGESIZE); 89169695Skan if (0 <= pages && 0 <= pagesize) 90169695Skan return pages * pagesize; 91169695Skan } 92169695Skan#endif 93169695Skan 94169695Skan#if HAVE_PSTAT_GETSTATIC 95169695Skan { /* This works on hpux11. */ 96169695Skan struct pst_static pss; 97169695Skan if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0)) 98169695Skan { 99169695Skan double pages = pss.physical_memory; 100169695Skan double pagesize = pss.page_size; 101169695Skan if (0 <= pages && 0 <= pagesize) 102169695Skan return pages * pagesize; 103169695Skan } 104169695Skan } 105169695Skan#endif 106169695Skan 107169695Skan#if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE 108169695Skan { /* This works on irix6. */ 109169695Skan struct rminfo realmem; 110169695Skan if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0) 111169695Skan { 112169695Skan double pagesize = sysconf (_SC_PAGESIZE); 113169695Skan double pages = realmem.physmem; 114169695Skan if (0 <= pages && 0 <= pagesize) 115169695Skan return pages * pagesize; 116169695Skan } 117169695Skan } 118169695Skan#endif 119169695Skan 120169695Skan#if HAVE_GETSYSINFO && defined GSI_PHYSMEM 121169695Skan { /* This works on Tru64 UNIX V4/5. */ 122169695Skan int physmem; 123169695Skan 124169695Skan if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem), 125169695Skan NULL, NULL, NULL) == 1) 126169695Skan { 127169695Skan double kbytes = physmem; 128169695Skan 129169695Skan if (0 <= kbytes) 130169695Skan return kbytes * 1024.0; 131169695Skan } 132169695Skan } 133169695Skan#endif 134169695Skan 135169695Skan#if HAVE_SYSCTL && defined HW_PHYSMEM 136169695Skan { /* This works on *bsd and darwin. */ 137169695Skan unsigned int physmem; 138169695Skan size_t len = sizeof physmem; 139169695Skan static int mib[2] = { CTL_HW, HW_PHYSMEM }; 140169695Skan 141169695Skan if (sysctl (mib, ARRAY_SIZE (mib), &physmem, &len, NULL, 0) == 0 142169695Skan && len == sizeof (physmem)) 143169695Skan return (double) physmem; 144169695Skan } 145169695Skan#endif 146169695Skan 147169695Skan#if HAVE__SYSTEM_CONFIGURATION 148169695Skan /* This works on AIX 4.3.3+. */ 149169695Skan return _system_configuration.physmem; 150169695Skan#endif 151169695Skan 152169695Skan#if defined _WIN32 153169695Skan { /* this works on windows */ 154169695Skan PFN_MS_EX pfnex; 155169695Skan HMODULE h = GetModuleHandle ("kernel32.dll"); 156169695Skan 157169695Skan if (!h) 158169695Skan return 0.0; 159169695Skan 160169695Skan /* Use GlobalMemoryStatusEx if available. */ 161169695Skan if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx"))) 162169695Skan { 163169695Skan lMEMORYSTATUSEX lms_ex; 164169695Skan lms_ex.dwLength = sizeof lms_ex; 165169695Skan if (!pfnex (&lms_ex)) 166169695Skan return 0.0; 167169695Skan return (double) lms_ex.ullTotalPhys; 168169695Skan } 169169695Skan 170169695Skan /* Fall back to GlobalMemoryStatus which is always available. 171169695Skan but returns wrong results for physical memory > 4GB. */ 172169695Skan else 173169695Skan { 174169695Skan MEMORYSTATUS ms; 175169695Skan GlobalMemoryStatus (&ms); 176169695Skan return (double) ms.dwTotalPhys; 177169695Skan } 178169695Skan } 179169695Skan#endif 180169695Skan 181169695Skan /* Return 0 if we can't determine the value. */ 182169695Skan return 0; 183169695Skan} 184169695Skan 185169695Skan/* Return the amount of physical memory available. */ 186169695Skandouble 187169695Skanphysmem_available (void) 188169695Skan{ 189169695Skan#if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE 190169695Skan { /* This works on linux-gnu, solaris2 and cygwin. */ 191169695Skan double pages = sysconf (_SC_AVPHYS_PAGES); 192169695Skan double pagesize = sysconf (_SC_PAGESIZE); 193169695Skan if (0 <= pages && 0 <= pagesize) 194169695Skan return pages * pagesize; 195169695Skan } 196169695Skan#endif 197169695Skan 198169695Skan#if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC 199169695Skan { /* This works on hpux11. */ 200169695Skan struct pst_static pss; 201169695Skan struct pst_dynamic psd; 202169695Skan if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0) 203169695Skan && 0 <= pstat_getdynamic (&psd, sizeof psd, 1, 0)) 204169695Skan { 205169695Skan double pages = psd.psd_free; 206169695Skan double pagesize = pss.page_size; 207169695Skan if (0 <= pages && 0 <= pagesize) 208169695Skan return pages * pagesize; 209169695Skan } 210169695Skan } 211169695Skan#endif 212169695Skan 213169695Skan#if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE 214169695Skan { /* This works on irix6. */ 215169695Skan struct rminfo realmem; 216169695Skan if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0) 217169695Skan { 218169695Skan double pagesize = sysconf (_SC_PAGESIZE); 219169695Skan double pages = realmem.availrmem; 220169695Skan if (0 <= pages && 0 <= pagesize) 221169695Skan return pages * pagesize; 222169695Skan } 223169695Skan } 224169695Skan#endif 225169695Skan 226169695Skan#if HAVE_TABLE && defined TBL_VMSTATS 227169695Skan { /* This works on Tru64 UNIX V4/5. */ 228169695Skan struct tbl_vmstats vmstats; 229169695Skan 230169695Skan if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1) 231169695Skan { 232169695Skan double pages = vmstats.free_count; 233169695Skan double pagesize = vmstats.pagesize; 234169695Skan 235169695Skan if (0 <= pages && 0 <= pagesize) 236169695Skan return pages * pagesize; 237169695Skan } 238169695Skan } 239169695Skan#endif 240169695Skan 241169695Skan#if HAVE_SYSCTL && defined HW_USERMEM 242169695Skan { /* This works on *bsd and darwin. */ 243169695Skan unsigned int usermem; 244169695Skan size_t len = sizeof usermem; 245169695Skan static int mib[2] = { CTL_HW, HW_USERMEM }; 246169695Skan 247169695Skan if (sysctl (mib, ARRAY_SIZE (mib), &usermem, &len, NULL, 0) == 0 248169695Skan && len == sizeof (usermem)) 249169695Skan return (double) usermem; 250169695Skan } 251169695Skan#endif 252169695Skan 253169695Skan#if defined _WIN32 254169695Skan { /* this works on windows */ 255169695Skan PFN_MS_EX pfnex; 256169695Skan HMODULE h = GetModuleHandle ("kernel32.dll"); 257169695Skan 258169695Skan if (!h) 259169695Skan return 0.0; 260169695Skan 261169695Skan /* Use GlobalMemoryStatusEx if available. */ 262169695Skan if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx"))) 263169695Skan { 264169695Skan lMEMORYSTATUSEX lms_ex; 265169695Skan lms_ex.dwLength = sizeof lms_ex; 266169695Skan if (!pfnex (&lms_ex)) 267169695Skan return 0.0; 268169695Skan return (double) lms_ex.ullAvailPhys; 269169695Skan } 270169695Skan 271169695Skan /* Fall back to GlobalMemoryStatus which is always available. 272169695Skan but returns wrong results for physical memory > 4GB */ 273169695Skan else 274169695Skan { 275169695Skan MEMORYSTATUS ms; 276169695Skan GlobalMemoryStatus (&ms); 277169695Skan return (double) ms.dwAvailPhys; 278169695Skan } 279169695Skan } 280169695Skan#endif 281169695Skan 282169695Skan /* Guess 25% of physical memory. */ 283169695Skan return physmem_total () / 4; 284169695Skan} 285169695Skan 286169695Skan 287169695Skan#if DEBUG 288169695Skan 289169695Skan# include <stdio.h> 290169695Skan# include <stdlib.h> 291169695Skan 292169695Skanint 293169695Skanmain (void) 294169695Skan{ 295169695Skan printf ("%12.f %12.f\n", physmem_total (), physmem_available ()); 296169695Skan exit (0); 297169695Skan} 298169695Skan 299169695Skan#endif /* DEBUG */ 300169695Skan 301169695Skan/* 302169695SkanLocal Variables: 303169695Skancompile-command: "gcc -DDEBUG -DHAVE_CONFIG_H -I.. -g -O -Wall -W physmem.c" 304169695SkanEnd: 305169695Skan*/ 306