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 185261188Spfg/* APPLE LOCAL begin retune gc params 6124839 */ 186261188Spfgunsigned int 187261188Spfgncpu_available (void) 188261188Spfg{ 189261188Spfg#if HAVE_SYSCTL && defined HW_AVAILCPU 190261188Spfg { /* This works on *bsd and darwin. */ 191261188Spfg unsigned int ncpu; 192261188Spfg size_t len = sizeof ncpu; 193261188Spfg static int mib[2] = { CTL_HW, HW_AVAILCPU }; 194261188Spfg 195261188Spfg if (sysctl (mib, ARRAY_SIZE (mib), &ncpu, &len, NULL, 0) == 0 196261188Spfg && len == sizeof (ncpu)) 197261188Spfg return ncpu; 198261188Spfg } 199261188Spfg#endif 200261188Spfg#if HAVE_SYSCTL && defined HW_NCPU 201261188Spfg { /* This works on *bsd and darwin. */ 202261188Spfg unsigned int ncpu; 203261188Spfg size_t len = sizeof ncpu; 204261188Spfg static int mib[2] = { CTL_HW, HW_NCPU }; 205261188Spfg 206261188Spfg if (sysctl (mib, ARRAY_SIZE (mib), &ncpu, &len, NULL, 0) == 0 207261188Spfg && len == sizeof (ncpu)) 208261188Spfg return ncpu; 209261188Spfg } 210261188Spfg#endif 211261188Spfg return 1; 212261188Spfg} 213261188Spfg/* APPLE LOCAL end retune gc params 6124839 */ 214261188Spfg 215169695Skan/* Return the amount of physical memory available. */ 216169695Skandouble 217169695Skanphysmem_available (void) 218169695Skan{ 219169695Skan#if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE 220169695Skan { /* This works on linux-gnu, solaris2 and cygwin. */ 221169695Skan double pages = sysconf (_SC_AVPHYS_PAGES); 222169695Skan double pagesize = sysconf (_SC_PAGESIZE); 223169695Skan if (0 <= pages && 0 <= pagesize) 224169695Skan return pages * pagesize; 225169695Skan } 226169695Skan#endif 227169695Skan 228169695Skan#if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC 229169695Skan { /* This works on hpux11. */ 230169695Skan struct pst_static pss; 231169695Skan struct pst_dynamic psd; 232169695Skan if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0) 233169695Skan && 0 <= pstat_getdynamic (&psd, sizeof psd, 1, 0)) 234169695Skan { 235169695Skan double pages = psd.psd_free; 236169695Skan double pagesize = pss.page_size; 237169695Skan if (0 <= pages && 0 <= pagesize) 238169695Skan return pages * pagesize; 239169695Skan } 240169695Skan } 241169695Skan#endif 242169695Skan 243169695Skan#if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE 244169695Skan { /* This works on irix6. */ 245169695Skan struct rminfo realmem; 246169695Skan if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0) 247169695Skan { 248169695Skan double pagesize = sysconf (_SC_PAGESIZE); 249169695Skan double pages = realmem.availrmem; 250169695Skan if (0 <= pages && 0 <= pagesize) 251169695Skan return pages * pagesize; 252169695Skan } 253169695Skan } 254169695Skan#endif 255169695Skan 256169695Skan#if HAVE_TABLE && defined TBL_VMSTATS 257169695Skan { /* This works on Tru64 UNIX V4/5. */ 258169695Skan struct tbl_vmstats vmstats; 259169695Skan 260169695Skan if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1) 261169695Skan { 262169695Skan double pages = vmstats.free_count; 263169695Skan double pagesize = vmstats.pagesize; 264169695Skan 265169695Skan if (0 <= pages && 0 <= pagesize) 266169695Skan return pages * pagesize; 267169695Skan } 268169695Skan } 269169695Skan#endif 270169695Skan 271169695Skan#if HAVE_SYSCTL && defined HW_USERMEM 272169695Skan { /* This works on *bsd and darwin. */ 273169695Skan unsigned int usermem; 274169695Skan size_t len = sizeof usermem; 275169695Skan static int mib[2] = { CTL_HW, HW_USERMEM }; 276169695Skan 277169695Skan if (sysctl (mib, ARRAY_SIZE (mib), &usermem, &len, NULL, 0) == 0 278169695Skan && len == sizeof (usermem)) 279169695Skan return (double) usermem; 280169695Skan } 281169695Skan#endif 282169695Skan 283169695Skan#if defined _WIN32 284169695Skan { /* this works on windows */ 285169695Skan PFN_MS_EX pfnex; 286169695Skan HMODULE h = GetModuleHandle ("kernel32.dll"); 287169695Skan 288169695Skan if (!h) 289169695Skan return 0.0; 290169695Skan 291169695Skan /* Use GlobalMemoryStatusEx if available. */ 292169695Skan if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx"))) 293169695Skan { 294169695Skan lMEMORYSTATUSEX lms_ex; 295169695Skan lms_ex.dwLength = sizeof lms_ex; 296169695Skan if (!pfnex (&lms_ex)) 297169695Skan return 0.0; 298169695Skan return (double) lms_ex.ullAvailPhys; 299169695Skan } 300169695Skan 301169695Skan /* Fall back to GlobalMemoryStatus which is always available. 302169695Skan but returns wrong results for physical memory > 4GB */ 303169695Skan else 304169695Skan { 305169695Skan MEMORYSTATUS ms; 306169695Skan GlobalMemoryStatus (&ms); 307169695Skan return (double) ms.dwAvailPhys; 308169695Skan } 309169695Skan } 310169695Skan#endif 311169695Skan 312169695Skan /* Guess 25% of physical memory. */ 313169695Skan return physmem_total () / 4; 314169695Skan} 315169695Skan 316169695Skan 317169695Skan#if DEBUG 318169695Skan 319169695Skan# include <stdio.h> 320169695Skan# include <stdlib.h> 321169695Skan 322169695Skanint 323169695Skanmain (void) 324169695Skan{ 325169695Skan printf ("%12.f %12.f\n", physmem_total (), physmem_available ()); 326169695Skan exit (0); 327169695Skan} 328169695Skan 329169695Skan#endif /* DEBUG */ 330169695Skan 331169695Skan/* 332169695SkanLocal Variables: 333169695Skancompile-command: "gcc -DDEBUG -DHAVE_CONFIG_H -I.. -g -O -Wall -W physmem.c" 334169695SkanEnd: 335169695Skan*/ 336