xref: /netbsd-src/external/gpl3/gdb/dist/libiberty/physmem.c (revision 7e120ff03ede3fe64e2c8620c01465d528502ddb)
198b9484cSchristos /* Calculate the size of physical memory.
2*7e120ff0Schristos    Copyright (C) 2000-2024 Free Software Foundation, Inc.
398b9484cSchristos 
498b9484cSchristos    This program is free software; you can redistribute it and/or modify
598b9484cSchristos    it under the terms of the GNU General Public License as published by
698b9484cSchristos    the Free Software Foundation; either version 2, or (at your option)
798b9484cSchristos    any later version.
898b9484cSchristos 
998b9484cSchristos    This program is distributed in the hope that it will be useful,
1098b9484cSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1198b9484cSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1298b9484cSchristos    GNU General Public License for more details.
1398b9484cSchristos 
1498b9484cSchristos    You should have received a copy of the GNU General Public License
1598b9484cSchristos    along with this program; if not, write to the Free Software Foundation,
1698b9484cSchristos    Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
1798b9484cSchristos 
1898b9484cSchristos /* Written by Paul Eggert.  */
1998b9484cSchristos 
2098b9484cSchristos #if HAVE_CONFIG_H
2198b9484cSchristos # include <config.h>
2298b9484cSchristos #endif
2398b9484cSchristos 
2498b9484cSchristos #if HAVE_UNISTD_H
2598b9484cSchristos # include <unistd.h>
2698b9484cSchristos #endif
2798b9484cSchristos 
2898b9484cSchristos #if HAVE_SYS_PSTAT_H
2998b9484cSchristos # include <sys/pstat.h>
3098b9484cSchristos #endif
3198b9484cSchristos 
3298b9484cSchristos #if HAVE_SYS_SYSMP_H
3398b9484cSchristos # include <sys/sysmp.h>
3498b9484cSchristos #endif
3598b9484cSchristos 
3698b9484cSchristos #if HAVE_SYS_SYSINFO_H && HAVE_MACHINE_HAL_SYSINFO_H
3798b9484cSchristos # include <sys/sysinfo.h>
3898b9484cSchristos # include <machine/hal_sysinfo.h>
3998b9484cSchristos #endif
4098b9484cSchristos 
4198b9484cSchristos #if HAVE_SYS_TABLE_H
4298b9484cSchristos # include <sys/table.h>
4398b9484cSchristos #endif
4498b9484cSchristos 
4598b9484cSchristos #include <sys/types.h>
4698b9484cSchristos 
4798b9484cSchristos #if HAVE_SYS_PARAM_H
4898b9484cSchristos # include <sys/param.h>
4998b9484cSchristos #endif
5098b9484cSchristos 
5198b9484cSchristos #if HAVE_SYS_SYSCTL_H
5298b9484cSchristos # include <sys/sysctl.h>
5398b9484cSchristos #endif
5498b9484cSchristos 
5598b9484cSchristos #if HAVE_SYS_SYSTEMCFG_H
5698b9484cSchristos # include <sys/systemcfg.h>
5798b9484cSchristos #endif
5898b9484cSchristos 
5998b9484cSchristos #ifdef _WIN32
6098b9484cSchristos # define WIN32_LEAN_AND_MEAN
6198b9484cSchristos # include <windows.h>
6298b9484cSchristos /*  MEMORYSTATUSEX is missing from older windows headers, so define
6398b9484cSchristos     a local replacement.  */
6498b9484cSchristos typedef struct
6598b9484cSchristos {
6698b9484cSchristos   DWORD dwLength;
6798b9484cSchristos   DWORD dwMemoryLoad;
6898b9484cSchristos   DWORDLONG ullTotalPhys;
6998b9484cSchristos   DWORDLONG ullAvailPhys;
7098b9484cSchristos   DWORDLONG ullTotalPageFile;
7198b9484cSchristos   DWORDLONG ullAvailPageFile;
7298b9484cSchristos   DWORDLONG ullTotalVirtual;
7398b9484cSchristos   DWORDLONG ullAvailVirtual;
7498b9484cSchristos   DWORDLONG ullAvailExtendedVirtual;
7598b9484cSchristos } lMEMORYSTATUSEX;
7698b9484cSchristos typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*);
7798b9484cSchristos #endif
7898b9484cSchristos 
7998b9484cSchristos #include "libiberty.h"
8098b9484cSchristos 
8198b9484cSchristos /* Return the total amount of physical memory.  */
8298b9484cSchristos double
8398b9484cSchristos physmem_total (void)
8498b9484cSchristos {
8598b9484cSchristos #if defined _SC_PHYS_PAGES && defined _SC_PAGESIZE
8698b9484cSchristos   { /* This works on linux-gnu, solaris2 and cygwin.  */
8798b9484cSchristos     double pages = sysconf (_SC_PHYS_PAGES);
8898b9484cSchristos     double pagesize = sysconf (_SC_PAGESIZE);
8998b9484cSchristos     if (0 <= pages && 0 <= pagesize)
9098b9484cSchristos       return pages * pagesize;
9198b9484cSchristos   }
9298b9484cSchristos #endif
9398b9484cSchristos 
9498b9484cSchristos #if HAVE_PSTAT_GETSTATIC
9598b9484cSchristos   { /* This works on hpux11.  */
9698b9484cSchristos     struct pst_static pss;
9798b9484cSchristos     if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0))
9898b9484cSchristos       {
9998b9484cSchristos 	double pages = pss.physical_memory;
10098b9484cSchristos 	double pagesize = pss.page_size;
10198b9484cSchristos 	if (0 <= pages && 0 <= pagesize)
10298b9484cSchristos 	  return pages * pagesize;
10398b9484cSchristos       }
10498b9484cSchristos   }
10598b9484cSchristos #endif
10698b9484cSchristos 
10798b9484cSchristos #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
10898b9484cSchristos   { /* This works on irix6. */
10998b9484cSchristos     struct rminfo realmem;
11098b9484cSchristos     if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0)
11198b9484cSchristos       {
11298b9484cSchristos 	double pagesize = sysconf (_SC_PAGESIZE);
11398b9484cSchristos 	double pages = realmem.physmem;
11498b9484cSchristos 	if (0 <= pages && 0 <= pagesize)
11598b9484cSchristos 	  return pages * pagesize;
11698b9484cSchristos       }
11798b9484cSchristos   }
11898b9484cSchristos #endif
11998b9484cSchristos 
12098b9484cSchristos #if HAVE_GETSYSINFO && defined GSI_PHYSMEM
12198b9484cSchristos   { /* This works on Tru64 UNIX V4/5.  */
12298b9484cSchristos     int physmem;
12398b9484cSchristos 
12498b9484cSchristos     if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem),
12598b9484cSchristos 		    NULL, NULL, NULL) == 1)
12698b9484cSchristos       {
12798b9484cSchristos 	double kbytes = physmem;
12898b9484cSchristos 
12998b9484cSchristos 	if (0 <= kbytes)
13098b9484cSchristos 	  return kbytes * 1024.0;
13198b9484cSchristos       }
13298b9484cSchristos   }
13398b9484cSchristos #endif
13498b9484cSchristos 
13598b9484cSchristos #if HAVE_SYSCTL && defined HW_PHYSMEM
13698b9484cSchristos   { /* This works on *bsd and darwin.  */
13798b9484cSchristos     unsigned int physmem;
13898b9484cSchristos     size_t len = sizeof physmem;
13998b9484cSchristos     static int mib[2] = { CTL_HW, HW_PHYSMEM };
14098b9484cSchristos 
14198b9484cSchristos     if (sysctl (mib, ARRAY_SIZE (mib), &physmem, &len, NULL, 0) == 0
14298b9484cSchristos 	&& len == sizeof (physmem))
14398b9484cSchristos       return (double) physmem;
14498b9484cSchristos   }
14598b9484cSchristos #endif
14698b9484cSchristos 
14798b9484cSchristos #if HAVE__SYSTEM_CONFIGURATION
14898b9484cSchristos   /* This works on AIX 4.3.3+.  */
14998b9484cSchristos   return _system_configuration.physmem;
15098b9484cSchristos #endif
15198b9484cSchristos 
15298b9484cSchristos #if defined _WIN32
15398b9484cSchristos   { /* this works on windows */
15498b9484cSchristos     PFN_MS_EX pfnex;
15598b9484cSchristos     HMODULE h = GetModuleHandle ("kernel32.dll");
15698b9484cSchristos 
15798b9484cSchristos     if (!h)
15898b9484cSchristos       return 0.0;
15998b9484cSchristos 
16098b9484cSchristos     /*  Use GlobalMemoryStatusEx if available.  */
16198b9484cSchristos     if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx")))
16298b9484cSchristos       {
16398b9484cSchristos 	lMEMORYSTATUSEX lms_ex;
16498b9484cSchristos 	lms_ex.dwLength = sizeof lms_ex;
16598b9484cSchristos 	if (!pfnex (&lms_ex))
16698b9484cSchristos 	  return 0.0;
16798b9484cSchristos 	return (double) lms_ex.ullTotalPhys;
16898b9484cSchristos       }
16998b9484cSchristos 
17098b9484cSchristos     /*  Fall back to GlobalMemoryStatus which is always available.
17198b9484cSchristos         but returns wrong results for physical memory > 4GB.  */
17298b9484cSchristos     else
17398b9484cSchristos       {
17498b9484cSchristos 	MEMORYSTATUS ms;
17598b9484cSchristos 	GlobalMemoryStatus (&ms);
17698b9484cSchristos 	return (double) ms.dwTotalPhys;
17798b9484cSchristos       }
17898b9484cSchristos   }
17998b9484cSchristos #endif
18098b9484cSchristos 
18198b9484cSchristos   /* Return 0 if we can't determine the value.  */
18298b9484cSchristos   return 0;
18398b9484cSchristos }
18498b9484cSchristos 
18598b9484cSchristos /* Return the amount of physical memory available.  */
18698b9484cSchristos double
18798b9484cSchristos physmem_available (void)
18898b9484cSchristos {
18998b9484cSchristos #if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE
19098b9484cSchristos   { /* This works on linux-gnu, solaris2 and cygwin.  */
19198b9484cSchristos     double pages = sysconf (_SC_AVPHYS_PAGES);
19298b9484cSchristos     double pagesize = sysconf (_SC_PAGESIZE);
19398b9484cSchristos     if (0 <= pages && 0 <= pagesize)
19498b9484cSchristos       return pages * pagesize;
19598b9484cSchristos   }
19698b9484cSchristos #endif
19798b9484cSchristos 
19898b9484cSchristos #if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC
19998b9484cSchristos   { /* This works on hpux11.  */
20098b9484cSchristos     struct pst_static pss;
20198b9484cSchristos     struct pst_dynamic psd;
20298b9484cSchristos     if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0)
20398b9484cSchristos 	&& 0 <= pstat_getdynamic (&psd, sizeof psd, 1, 0))
20498b9484cSchristos       {
20598b9484cSchristos 	double pages = psd.psd_free;
20698b9484cSchristos 	double pagesize = pss.page_size;
20798b9484cSchristos 	if (0 <= pages && 0 <= pagesize)
20898b9484cSchristos 	  return pages * pagesize;
20998b9484cSchristos       }
21098b9484cSchristos   }
21198b9484cSchristos #endif
21298b9484cSchristos 
21398b9484cSchristos #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
21498b9484cSchristos   { /* This works on irix6. */
21598b9484cSchristos     struct rminfo realmem;
21698b9484cSchristos     if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0)
21798b9484cSchristos       {
21898b9484cSchristos 	double pagesize = sysconf (_SC_PAGESIZE);
21998b9484cSchristos 	double pages = realmem.availrmem;
22098b9484cSchristos 	if (0 <= pages && 0 <= pagesize)
22198b9484cSchristos 	  return pages * pagesize;
22298b9484cSchristos       }
22398b9484cSchristos   }
22498b9484cSchristos #endif
22598b9484cSchristos 
22698b9484cSchristos #if HAVE_TABLE && defined TBL_VMSTATS
22798b9484cSchristos   { /* This works on Tru64 UNIX V4/5.  */
22898b9484cSchristos     struct tbl_vmstats vmstats;
22998b9484cSchristos 
23098b9484cSchristos     if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1)
23198b9484cSchristos       {
23298b9484cSchristos 	double pages = vmstats.free_count;
23398b9484cSchristos 	double pagesize = vmstats.pagesize;
23498b9484cSchristos 
23598b9484cSchristos 	if (0 <= pages && 0 <= pagesize)
23698b9484cSchristos 	  return pages * pagesize;
23798b9484cSchristos       }
23898b9484cSchristos   }
23998b9484cSchristos #endif
24098b9484cSchristos 
24198b9484cSchristos #if HAVE_SYSCTL && defined HW_USERMEM
24298b9484cSchristos   { /* This works on *bsd and darwin.  */
24398b9484cSchristos     unsigned int usermem;
24498b9484cSchristos     size_t len = sizeof usermem;
24598b9484cSchristos     static int mib[2] = { CTL_HW, HW_USERMEM };
24698b9484cSchristos 
24798b9484cSchristos     if (sysctl (mib, ARRAY_SIZE (mib), &usermem, &len, NULL, 0) == 0
24898b9484cSchristos 	&& len == sizeof (usermem))
24998b9484cSchristos       return (double) usermem;
25098b9484cSchristos   }
25198b9484cSchristos #endif
25298b9484cSchristos 
25398b9484cSchristos #if defined _WIN32
25498b9484cSchristos   { /* this works on windows */
25598b9484cSchristos     PFN_MS_EX pfnex;
25698b9484cSchristos     HMODULE h = GetModuleHandle ("kernel32.dll");
25798b9484cSchristos 
25898b9484cSchristos     if (!h)
25998b9484cSchristos       return 0.0;
26098b9484cSchristos 
26198b9484cSchristos     /*  Use GlobalMemoryStatusEx if available.  */
26298b9484cSchristos     if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx")))
26398b9484cSchristos       {
26498b9484cSchristos 	lMEMORYSTATUSEX lms_ex;
26598b9484cSchristos 	lms_ex.dwLength = sizeof lms_ex;
26698b9484cSchristos 	if (!pfnex (&lms_ex))
26798b9484cSchristos 	  return 0.0;
26898b9484cSchristos 	return (double) lms_ex.ullAvailPhys;
26998b9484cSchristos       }
27098b9484cSchristos 
27198b9484cSchristos     /*  Fall back to GlobalMemoryStatus which is always available.
27298b9484cSchristos         but returns wrong results for physical memory > 4GB  */
27398b9484cSchristos     else
27498b9484cSchristos       {
27598b9484cSchristos 	MEMORYSTATUS ms;
27698b9484cSchristos 	GlobalMemoryStatus (&ms);
27798b9484cSchristos 	return (double) ms.dwAvailPhys;
27898b9484cSchristos       }
27998b9484cSchristos   }
28098b9484cSchristos #endif
28198b9484cSchristos 
28298b9484cSchristos   /* Guess 25% of physical memory.  */
28398b9484cSchristos   return physmem_total () / 4;
28498b9484cSchristos }
28598b9484cSchristos 
28698b9484cSchristos 
28798b9484cSchristos #if DEBUG
28898b9484cSchristos 
28998b9484cSchristos # include <stdio.h>
29098b9484cSchristos # include <stdlib.h>
29198b9484cSchristos 
29298b9484cSchristos int
29398b9484cSchristos main (void)
29498b9484cSchristos {
29598b9484cSchristos   printf ("%12.f %12.f\n", physmem_total (), physmem_available ());
29698b9484cSchristos   exit (0);
29798b9484cSchristos }
29898b9484cSchristos 
29998b9484cSchristos #endif /* DEBUG */
30098b9484cSchristos 
30198b9484cSchristos /*
30298b9484cSchristos Local Variables:
30398b9484cSchristos compile-command: "gcc -DDEBUG -DHAVE_CONFIG_H -I.. -g -O -Wall -W physmem.c"
30498b9484cSchristos End:
30598b9484cSchristos */
306