LCOV - code coverage report
Current view: top level - lib - physmem.c (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 10 12 83.3 %
Date: 2018-01-30 Functions: 2 2 100.0 %

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

Generated by: LCOV version 1.10