Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* Calculate the size of physical memory.
  2.    Copyright 2000, 2001, 2003, 2004, 2005 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. */
  306.