root/maint/gnulib/lib/physmem.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. physmem_total
  2. physmem_available
  3. main

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

/* [previous][next][first][last][top][bottom][index][help] */