(root)/
binutils-2.41/
libiberty/
physmem.c
       1  /* Calculate the size of physical memory.
       2     Copyright (C) 2000-2023 Free Software Foundation, Inc.
       3  
       4     This program is free software; you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation; either version 2, or (at your option)
       7     any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program; if not, write to the Free Software Foundation,
      16     Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
      17  
      18  /* Written by Paul Eggert.  */
      19  
      20  #if HAVE_CONFIG_H
      21  # include <config.h>
      22  #endif
      23  
      24  #if HAVE_UNISTD_H
      25  # include <unistd.h>
      26  #endif
      27  
      28  #if HAVE_SYS_PSTAT_H
      29  # include <sys/pstat.h>
      30  #endif
      31  
      32  #if HAVE_SYS_SYSMP_H
      33  # include <sys/sysmp.h>
      34  #endif
      35  
      36  #if HAVE_SYS_SYSINFO_H && HAVE_MACHINE_HAL_SYSINFO_H
      37  # include <sys/sysinfo.h>
      38  # include <machine/hal_sysinfo.h>
      39  #endif
      40  
      41  #if HAVE_SYS_TABLE_H
      42  # include <sys/table.h>
      43  #endif
      44  
      45  #include <sys/types.h>
      46  
      47  #if HAVE_SYS_PARAM_H
      48  # include <sys/param.h>
      49  #endif
      50  
      51  #if HAVE_SYS_SYSCTL_H
      52  # include <sys/sysctl.h>
      53  #endif
      54  
      55  #if HAVE_SYS_SYSTEMCFG_H
      56  # include <sys/systemcfg.h>
      57  #endif
      58  
      59  #ifdef _WIN32
      60  # define WIN32_LEAN_AND_MEAN
      61  # include <windows.h>
      62  /*  MEMORYSTATUSEX is missing from older windows headers, so define
      63      a local replacement.  */
      64  typedef struct
      65  {
      66    DWORD dwLength;
      67    DWORD dwMemoryLoad;
      68    DWORDLONG ullTotalPhys;
      69    DWORDLONG ullAvailPhys;
      70    DWORDLONG ullTotalPageFile;
      71    DWORDLONG ullAvailPageFile;
      72    DWORDLONG ullTotalVirtual;
      73    DWORDLONG ullAvailVirtual;
      74    DWORDLONG ullAvailExtendedVirtual;
      75  } lMEMORYSTATUSEX;
      76  typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*);
      77  #endif
      78  
      79  #include "libiberty.h"
      80  
      81  /* Return the total amount of physical memory.  */
      82  double
      83  physmem_total (void)
      84  {
      85  #if defined _SC_PHYS_PAGES && defined _SC_PAGESIZE
      86    { /* This works on linux-gnu, solaris2 and cygwin.  */
      87      double pages = sysconf (_SC_PHYS_PAGES);
      88      double pagesize = sysconf (_SC_PAGESIZE);
      89      if (0 <= pages && 0 <= pagesize)
      90        return pages * pagesize;
      91    }
      92  #endif
      93  
      94  #if HAVE_PSTAT_GETSTATIC
      95    { /* This works on hpux11.  */
      96      struct pst_static pss;
      97      if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0))
      98        {
      99  	double pages = pss.physical_memory;
     100  	double pagesize = pss.page_size;
     101  	if (0 <= pages && 0 <= pagesize)
     102  	  return pages * pagesize;
     103        }
     104    }
     105  #endif
     106  
     107  #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
     108    { /* This works on irix6. */
     109      struct rminfo realmem;
     110      if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0)
     111        {
     112  	double pagesize = sysconf (_SC_PAGESIZE);
     113  	double pages = realmem.physmem;
     114  	if (0 <= pages && 0 <= pagesize)
     115  	  return pages * pagesize;
     116        }
     117    }
     118  #endif
     119  
     120  #if HAVE_GETSYSINFO && defined GSI_PHYSMEM
     121    { /* This works on Tru64 UNIX V4/5.  */
     122      int physmem;
     123  
     124      if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem),
     125  		    NULL, NULL, NULL) == 1)
     126        {
     127  	double kbytes = physmem;
     128  
     129  	if (0 <= kbytes)
     130  	  return kbytes * 1024.0;
     131        }
     132    }
     133  #endif
     134  
     135  #if HAVE_SYSCTL && defined HW_PHYSMEM
     136    { /* This works on *bsd and darwin.  */
     137      unsigned int physmem;
     138      size_t len = sizeof physmem;
     139      static int mib[2] = { CTL_HW, HW_PHYSMEM };
     140  
     141      if (sysctl (mib, ARRAY_SIZE (mib), &physmem, &len, NULL, 0) == 0
     142  	&& len == sizeof (physmem))
     143        return (double) physmem;
     144    }
     145  #endif
     146  
     147  #if HAVE__SYSTEM_CONFIGURATION
     148    /* This works on AIX 4.3.3+.  */
     149    return _system_configuration.physmem;
     150  #endif
     151  
     152  #if defined _WIN32
     153    { /* this works on windows */
     154      PFN_MS_EX pfnex;
     155      HMODULE h = GetModuleHandle ("kernel32.dll");
     156  
     157      if (!h)
     158        return 0.0;
     159  
     160      /*  Use GlobalMemoryStatusEx if available.  */
     161      if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx")))
     162        {
     163  	lMEMORYSTATUSEX lms_ex;
     164  	lms_ex.dwLength = sizeof lms_ex;
     165  	if (!pfnex (&lms_ex))
     166  	  return 0.0;
     167  	return (double) lms_ex.ullTotalPhys;
     168        }
     169  
     170      /*  Fall back to GlobalMemoryStatus which is always available.
     171          but returns wrong results for physical memory > 4GB.  */
     172      else
     173        {
     174  	MEMORYSTATUS ms;
     175  	GlobalMemoryStatus (&ms);
     176  	return (double) ms.dwTotalPhys;
     177        }
     178    }
     179  #endif
     180  
     181    /* Return 0 if we can't determine the value.  */
     182    return 0;
     183  }
     184  
     185  /* Return the amount of physical memory available.  */
     186  double
     187  physmem_available (void)
     188  {
     189  #if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE
     190    { /* This works on linux-gnu, solaris2 and cygwin.  */
     191      double pages = sysconf (_SC_AVPHYS_PAGES);
     192      double pagesize = sysconf (_SC_PAGESIZE);
     193      if (0 <= pages && 0 <= pagesize)
     194        return pages * pagesize;
     195    }
     196  #endif
     197  
     198  #if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC
     199    { /* This works on hpux11.  */
     200      struct pst_static pss;
     201      struct pst_dynamic psd;
     202      if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0)
     203  	&& 0 <= pstat_getdynamic (&psd, sizeof psd, 1, 0))
     204        {
     205  	double pages = psd.psd_free;
     206  	double pagesize = pss.page_size;
     207  	if (0 <= pages && 0 <= pagesize)
     208  	  return pages * pagesize;
     209        }
     210    }
     211  #endif
     212  
     213  #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
     214    { /* This works on irix6. */
     215      struct rminfo realmem;
     216      if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0)
     217        {
     218  	double pagesize = sysconf (_SC_PAGESIZE);
     219  	double pages = realmem.availrmem;
     220  	if (0 <= pages && 0 <= pagesize)
     221  	  return pages * pagesize;
     222        }
     223    }
     224  #endif
     225  
     226  #if HAVE_TABLE && defined TBL_VMSTATS
     227    { /* This works on Tru64 UNIX V4/5.  */
     228      struct tbl_vmstats vmstats;
     229  
     230      if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1)
     231        {
     232  	double pages = vmstats.free_count;
     233  	double pagesize = vmstats.pagesize;
     234  
     235  	if (0 <= pages && 0 <= pagesize)
     236  	  return pages * pagesize;
     237        }
     238    }
     239  #endif
     240  
     241  #if HAVE_SYSCTL && defined HW_USERMEM
     242    { /* This works on *bsd and darwin.  */
     243      unsigned int usermem;
     244      size_t len = sizeof usermem;
     245      static int mib[2] = { CTL_HW, HW_USERMEM };
     246  
     247      if (sysctl (mib, ARRAY_SIZE (mib), &usermem, &len, NULL, 0) == 0
     248  	&& len == sizeof (usermem))
     249        return (double) usermem;
     250    }
     251  #endif
     252  
     253  #if defined _WIN32
     254    { /* this works on windows */
     255      PFN_MS_EX pfnex;
     256      HMODULE h = GetModuleHandle ("kernel32.dll");
     257  
     258      if (!h)
     259        return 0.0;
     260  
     261      /*  Use GlobalMemoryStatusEx if available.  */
     262      if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx")))
     263        {
     264  	lMEMORYSTATUSEX lms_ex;
     265  	lms_ex.dwLength = sizeof lms_ex;
     266  	if (!pfnex (&lms_ex))
     267  	  return 0.0;
     268  	return (double) lms_ex.ullAvailPhys;
     269        }
     270  
     271      /*  Fall back to GlobalMemoryStatus which is always available.
     272          but returns wrong results for physical memory > 4GB  */
     273      else
     274        {
     275  	MEMORYSTATUS ms;
     276  	GlobalMemoryStatus (&ms);
     277  	return (double) ms.dwAvailPhys;
     278        }
     279    }
     280  #endif
     281  
     282    /* Guess 25% of physical memory.  */
     283    return physmem_total () / 4;
     284  }
     285  
     286  
     287  #if DEBUG
     288  
     289  # include <stdio.h>
     290  # include <stdlib.h>
     291  
     292  int
     293  main (void)
     294  {
     295    printf ("%12.f %12.f\n", physmem_total (), physmem_available ());
     296    exit (0);
     297  }
     298  
     299  #endif /* DEBUG */
     300  
     301  /*
     302  Local Variables:
     303  compile-command: "gcc -DDEBUG -DHAVE_CONFIG_H -I.. -g -O -Wall -W physmem.c"
     304  End:
     305  */