19588ddcfSespie /* Calculate the size of physical memory.
2*150b7e42Smiod Copyright 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
39588ddcfSespie
49588ddcfSespie This program is free software; you can redistribute it and/or modify
59588ddcfSespie it under the terms of the GNU General Public License as published by
69588ddcfSespie the Free Software Foundation; either version 2, or (at your option)
79588ddcfSespie any later version.
89588ddcfSespie
99588ddcfSespie This program is distributed in the hope that it will be useful,
109588ddcfSespie but WITHOUT ANY WARRANTY; without even the implied warranty of
119588ddcfSespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
129588ddcfSespie GNU General Public License for more details.
139588ddcfSespie
149588ddcfSespie You should have received a copy of the GNU General Public License
159588ddcfSespie along with this program; if not, write to the Free Software Foundation,
16*150b7e42Smiod Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
179588ddcfSespie
189588ddcfSespie /* Written by Paul Eggert. */
199588ddcfSespie
209588ddcfSespie #if HAVE_CONFIG_H
219588ddcfSespie # include <config.h>
229588ddcfSespie #endif
239588ddcfSespie
249588ddcfSespie #if HAVE_UNISTD_H
259588ddcfSespie # include <unistd.h>
269588ddcfSespie #endif
279588ddcfSespie
289588ddcfSespie #if HAVE_SYS_PSTAT_H
299588ddcfSespie # include <sys/pstat.h>
309588ddcfSespie #endif
319588ddcfSespie
329588ddcfSespie #if HAVE_SYS_SYSMP_H
339588ddcfSespie # include <sys/sysmp.h>
349588ddcfSespie #endif
359588ddcfSespie
369588ddcfSespie #if HAVE_SYS_SYSINFO_H && HAVE_MACHINE_HAL_SYSINFO_H
379588ddcfSespie # include <sys/sysinfo.h>
389588ddcfSespie # include <machine/hal_sysinfo.h>
399588ddcfSespie #endif
409588ddcfSespie
419588ddcfSespie #if HAVE_SYS_TABLE_H
429588ddcfSespie # include <sys/table.h>
439588ddcfSespie #endif
449588ddcfSespie
459588ddcfSespie #include <sys/types.h>
469588ddcfSespie
479588ddcfSespie #if HAVE_SYS_PARAM_H
489588ddcfSespie # include <sys/param.h>
499588ddcfSespie #endif
509588ddcfSespie
519588ddcfSespie #if HAVE_SYS_SYSCTL_H
529588ddcfSespie # include <sys/sysctl.h>
539588ddcfSespie #endif
549588ddcfSespie
559588ddcfSespie #if HAVE_SYS_SYSTEMCFG_H
569588ddcfSespie # include <sys/systemcfg.h>
579588ddcfSespie #endif
589588ddcfSespie
599588ddcfSespie #ifdef _WIN32
609588ddcfSespie # define WIN32_LEAN_AND_MEAN
619588ddcfSespie # include <windows.h>
629588ddcfSespie /* MEMORYSTATUSEX is missing from older windows headers, so define
639588ddcfSespie a local replacement. */
649588ddcfSespie typedef struct
659588ddcfSespie {
669588ddcfSespie DWORD dwLength;
679588ddcfSespie DWORD dwMemoryLoad;
689588ddcfSespie DWORDLONG ullTotalPhys;
699588ddcfSespie DWORDLONG ullAvailPhys;
709588ddcfSespie DWORDLONG ullTotalPageFile;
719588ddcfSespie DWORDLONG ullAvailPageFile;
729588ddcfSespie DWORDLONG ullTotalVirtual;
739588ddcfSespie DWORDLONG ullAvailVirtual;
749588ddcfSespie DWORDLONG ullAvailExtendedVirtual;
759588ddcfSespie } lMEMORYSTATUSEX;
769588ddcfSespie typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*);
779588ddcfSespie #endif
789588ddcfSespie
799588ddcfSespie #include "libiberty.h"
809588ddcfSespie
819588ddcfSespie /* Return the total amount of physical memory. */
829588ddcfSespie double
physmem_total(void)83*150b7e42Smiod physmem_total (void)
849588ddcfSespie {
859588ddcfSespie #if defined _SC_PHYS_PAGES && defined _SC_PAGESIZE
869588ddcfSespie { /* This works on linux-gnu, solaris2 and cygwin. */
879588ddcfSespie double pages = sysconf (_SC_PHYS_PAGES);
889588ddcfSespie double pagesize = sysconf (_SC_PAGESIZE);
899588ddcfSespie if (0 <= pages && 0 <= pagesize)
909588ddcfSespie return pages * pagesize;
919588ddcfSespie }
929588ddcfSespie #endif
939588ddcfSespie
949588ddcfSespie #if HAVE_PSTAT_GETSTATIC
959588ddcfSespie { /* This works on hpux11. */
969588ddcfSespie struct pst_static pss;
979588ddcfSespie if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0))
989588ddcfSespie {
999588ddcfSespie double pages = pss.physical_memory;
1009588ddcfSespie double pagesize = pss.page_size;
1019588ddcfSespie if (0 <= pages && 0 <= pagesize)
1029588ddcfSespie return pages * pagesize;
1039588ddcfSespie }
1049588ddcfSespie }
1059588ddcfSespie #endif
1069588ddcfSespie
1079588ddcfSespie #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
1089588ddcfSespie { /* This works on irix6. */
1099588ddcfSespie struct rminfo realmem;
1109588ddcfSespie if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0)
1119588ddcfSespie {
1129588ddcfSespie double pagesize = sysconf (_SC_PAGESIZE);
1139588ddcfSespie double pages = realmem.physmem;
1149588ddcfSespie if (0 <= pages && 0 <= pagesize)
1159588ddcfSespie return pages * pagesize;
1169588ddcfSespie }
1179588ddcfSespie }
1189588ddcfSespie #endif
1199588ddcfSespie
1209588ddcfSespie #if HAVE_GETSYSINFO && defined GSI_PHYSMEM
1219588ddcfSespie { /* This works on Tru64 UNIX V4/5. */
1229588ddcfSespie int physmem;
1239588ddcfSespie
1249588ddcfSespie if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem),
1259588ddcfSespie NULL, NULL, NULL) == 1)
1269588ddcfSespie {
1279588ddcfSespie double kbytes = physmem;
1289588ddcfSespie
1299588ddcfSespie if (0 <= kbytes)
1309588ddcfSespie return kbytes * 1024.0;
1319588ddcfSespie }
1329588ddcfSespie }
1339588ddcfSespie #endif
1349588ddcfSespie
1359588ddcfSespie #if HAVE_SYSCTL && defined HW_PHYSMEM
1369588ddcfSespie { /* This works on *bsd and darwin. */
1379588ddcfSespie unsigned int physmem;
1389588ddcfSespie size_t len = sizeof physmem;
1399588ddcfSespie static int mib[2] = { CTL_HW, HW_PHYSMEM };
1409588ddcfSespie
1419588ddcfSespie if (sysctl (mib, ARRAY_SIZE (mib), &physmem, &len, NULL, 0) == 0
1429588ddcfSespie && len == sizeof (physmem))
1439588ddcfSespie return (double) physmem;
1449588ddcfSespie }
1459588ddcfSespie #endif
1469588ddcfSespie
1479588ddcfSespie #if HAVE__SYSTEM_CONFIGURATION
148*150b7e42Smiod /* This works on AIX 4.3.3+. */
1499588ddcfSespie return _system_configuration.physmem;
1509588ddcfSespie #endif
1519588ddcfSespie
1529588ddcfSespie #if defined _WIN32
1539588ddcfSespie { /* this works on windows */
1549588ddcfSespie PFN_MS_EX pfnex;
1559588ddcfSespie HMODULE h = GetModuleHandle ("kernel32.dll");
1569588ddcfSespie
1579588ddcfSespie if (!h)
1589588ddcfSespie return 0.0;
1599588ddcfSespie
1609588ddcfSespie /* Use GlobalMemoryStatusEx if available. */
1619588ddcfSespie if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx")))
1629588ddcfSespie {
1639588ddcfSespie lMEMORYSTATUSEX lms_ex;
1649588ddcfSespie lms_ex.dwLength = sizeof lms_ex;
1659588ddcfSespie if (!pfnex (&lms_ex))
1669588ddcfSespie return 0.0;
1679588ddcfSespie return (double) lms_ex.ullTotalPhys;
1689588ddcfSespie }
1699588ddcfSespie
1709588ddcfSespie /* Fall back to GlobalMemoryStatus which is always available.
1719588ddcfSespie but returns wrong results for physical memory > 4GB. */
1729588ddcfSespie else
1739588ddcfSespie {
1749588ddcfSespie MEMORYSTATUS ms;
1759588ddcfSespie GlobalMemoryStatus (&ms);
1769588ddcfSespie return (double) ms.dwTotalPhys;
1779588ddcfSespie }
1789588ddcfSespie }
1799588ddcfSespie #endif
1809588ddcfSespie
1819588ddcfSespie /* Return 0 if we can't determine the value. */
1829588ddcfSespie return 0;
1839588ddcfSespie }
1849588ddcfSespie
1859588ddcfSespie /* Return the amount of physical memory available. */
1869588ddcfSespie double
physmem_available(void)187*150b7e42Smiod physmem_available (void)
1889588ddcfSespie {
1899588ddcfSespie #if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE
1909588ddcfSespie { /* This works on linux-gnu, solaris2 and cygwin. */
1919588ddcfSespie double pages = sysconf (_SC_AVPHYS_PAGES);
1929588ddcfSespie double pagesize = sysconf (_SC_PAGESIZE);
1939588ddcfSespie if (0 <= pages && 0 <= pagesize)
1949588ddcfSespie return pages * pagesize;
1959588ddcfSespie }
1969588ddcfSespie #endif
1979588ddcfSespie
1989588ddcfSespie #if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC
1999588ddcfSespie { /* This works on hpux11. */
2009588ddcfSespie struct pst_static pss;
2019588ddcfSespie struct pst_dynamic psd;
2029588ddcfSespie if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0)
2039588ddcfSespie && 0 <= pstat_getdynamic (&psd, sizeof psd, 1, 0))
2049588ddcfSespie {
2059588ddcfSespie double pages = psd.psd_free;
2069588ddcfSespie double pagesize = pss.page_size;
2079588ddcfSespie if (0 <= pages && 0 <= pagesize)
2089588ddcfSespie return pages * pagesize;
2099588ddcfSespie }
2109588ddcfSespie }
2119588ddcfSespie #endif
2129588ddcfSespie
2139588ddcfSespie #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
2149588ddcfSespie { /* This works on irix6. */
2159588ddcfSespie struct rminfo realmem;
2169588ddcfSespie if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0)
2179588ddcfSespie {
2189588ddcfSespie double pagesize = sysconf (_SC_PAGESIZE);
2199588ddcfSespie double pages = realmem.availrmem;
2209588ddcfSespie if (0 <= pages && 0 <= pagesize)
2219588ddcfSespie return pages * pagesize;
2229588ddcfSespie }
2239588ddcfSespie }
2249588ddcfSespie #endif
2259588ddcfSespie
2269588ddcfSespie #if HAVE_TABLE && defined TBL_VMSTATS
2279588ddcfSespie { /* This works on Tru64 UNIX V4/5. */
2289588ddcfSespie struct tbl_vmstats vmstats;
2299588ddcfSespie
2309588ddcfSespie if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1)
2319588ddcfSespie {
2329588ddcfSespie double pages = vmstats.free_count;
2339588ddcfSespie double pagesize = vmstats.pagesize;
2349588ddcfSespie
2359588ddcfSespie if (0 <= pages && 0 <= pagesize)
2369588ddcfSespie return pages * pagesize;
2379588ddcfSespie }
2389588ddcfSespie }
2399588ddcfSespie #endif
2409588ddcfSespie
2419588ddcfSespie #if HAVE_SYSCTL && defined HW_USERMEM
2429588ddcfSespie { /* This works on *bsd and darwin. */
2439588ddcfSespie unsigned int usermem;
2449588ddcfSespie size_t len = sizeof usermem;
2459588ddcfSespie static int mib[2] = { CTL_HW, HW_USERMEM };
2469588ddcfSespie
2479588ddcfSespie if (sysctl (mib, ARRAY_SIZE (mib), &usermem, &len, NULL, 0) == 0
2489588ddcfSespie && len == sizeof (usermem))
2499588ddcfSespie return (double) usermem;
2509588ddcfSespie }
2519588ddcfSespie #endif
2529588ddcfSespie
2539588ddcfSespie #if defined _WIN32
2549588ddcfSespie { /* this works on windows */
2559588ddcfSespie PFN_MS_EX pfnex;
2569588ddcfSespie HMODULE h = GetModuleHandle ("kernel32.dll");
2579588ddcfSespie
2589588ddcfSespie if (!h)
2599588ddcfSespie return 0.0;
2609588ddcfSespie
2619588ddcfSespie /* Use GlobalMemoryStatusEx if available. */
2629588ddcfSespie if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx")))
2639588ddcfSespie {
2649588ddcfSespie lMEMORYSTATUSEX lms_ex;
2659588ddcfSespie lms_ex.dwLength = sizeof lms_ex;
2669588ddcfSespie if (!pfnex (&lms_ex))
2679588ddcfSespie return 0.0;
2689588ddcfSespie return (double) lms_ex.ullAvailPhys;
2699588ddcfSespie }
2709588ddcfSespie
2719588ddcfSespie /* Fall back to GlobalMemoryStatus which is always available.
2729588ddcfSespie but returns wrong results for physical memory > 4GB */
2739588ddcfSespie else
2749588ddcfSespie {
2759588ddcfSespie MEMORYSTATUS ms;
2769588ddcfSespie GlobalMemoryStatus (&ms);
2779588ddcfSespie return (double) ms.dwAvailPhys;
2789588ddcfSespie }
2799588ddcfSespie }
2809588ddcfSespie #endif
2819588ddcfSespie
2829588ddcfSespie /* Guess 25% of physical memory. */
2839588ddcfSespie return physmem_total () / 4;
2849588ddcfSespie }
2859588ddcfSespie
2869588ddcfSespie
2879588ddcfSespie #if DEBUG
2889588ddcfSespie
2899588ddcfSespie # include <stdio.h>
2909588ddcfSespie # include <stdlib.h>
2919588ddcfSespie
2929588ddcfSespie int
main(void)293*150b7e42Smiod main (void)
2949588ddcfSespie {
2959588ddcfSespie printf ("%12.f %12.f\n", physmem_total (), physmem_available ());
2969588ddcfSespie exit (0);
2979588ddcfSespie }
2989588ddcfSespie
2999588ddcfSespie #endif /* DEBUG */
3009588ddcfSespie
3019588ddcfSespie /*
3029588ddcfSespie Local Variables:
3039588ddcfSespie compile-command: "gcc -DDEBUG -DHAVE_CONFIG_H -I.. -g -O -Wall -W physmem.c"
3049588ddcfSespie End:
3059588ddcfSespie */
306