xref: /openbsd-src/gnu/lib/libiberty/src/physmem.c (revision 150b7e42cfa21e6546d96ae514ca23e80d970ac7)
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