Back to index

cell-binutils  2.17cvs20070401
physmem.c
Go to the documentation of this file.
00001 /* Calculate the size of physical memory.
00002    Copyright 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
00003 
00004    This program is free software; you can redistribute it and/or modify
00005    it under the terms of the GNU General Public License as published by
00006    the Free Software Foundation; either version 2, or (at your option)
00007    any later version.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012    GNU General Public License for more details.
00013 
00014    You should have received a copy of the GNU General Public License
00015    along with this program; if not, write to the Free Software Foundation,
00016    Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00017 
00018 /* Written by Paul Eggert.  */
00019 
00020 #if HAVE_CONFIG_H
00021 # include <config.h>
00022 #endif
00023 
00024 #if HAVE_UNISTD_H
00025 # include <unistd.h>
00026 #endif
00027 
00028 #if HAVE_SYS_PSTAT_H
00029 # include <sys/pstat.h>
00030 #endif
00031 
00032 #if HAVE_SYS_SYSMP_H
00033 # include <sys/sysmp.h>
00034 #endif
00035 
00036 #if HAVE_SYS_SYSINFO_H && HAVE_MACHINE_HAL_SYSINFO_H
00037 # include <sys/sysinfo.h>
00038 # include <machine/hal_sysinfo.h>
00039 #endif
00040 
00041 #if HAVE_SYS_TABLE_H
00042 # include <sys/table.h>
00043 #endif
00044 
00045 #include <sys/types.h>
00046 
00047 #if HAVE_SYS_PARAM_H
00048 # include <sys/param.h>
00049 #endif
00050 
00051 #if HAVE_SYS_SYSCTL_H
00052 # include <sys/sysctl.h>
00053 #endif
00054 
00055 #if HAVE_SYS_SYSTEMCFG_H
00056 # include <sys/systemcfg.h>
00057 #endif
00058 
00059 #ifdef _WIN32
00060 # define WIN32_LEAN_AND_MEAN
00061 # include <windows.h>
00062 /*  MEMORYSTATUSEX is missing from older windows headers, so define
00063     a local replacement.  */
00064 typedef struct
00065 {
00066   DWORD dwLength;
00067   DWORD dwMemoryLoad;
00068   DWORDLONG ullTotalPhys;
00069   DWORDLONG ullAvailPhys;
00070   DWORDLONG ullTotalPageFile;
00071   DWORDLONG ullAvailPageFile;
00072   DWORDLONG ullTotalVirtual;
00073   DWORDLONG ullAvailVirtual;
00074   DWORDLONG ullAvailExtendedVirtual;
00075 } lMEMORYSTATUSEX;
00076 typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*);
00077 #endif
00078 
00079 #include "libiberty.h"
00080 
00081 /* Return the total amount of physical memory.  */
00082 double
00083 physmem_total (void)
00084 {
00085 #if defined _SC_PHYS_PAGES && defined _SC_PAGESIZE
00086   { /* This works on linux-gnu, solaris2 and cygwin.  */
00087     double pages = sysconf (_SC_PHYS_PAGES);
00088     double pagesize = sysconf (_SC_PAGESIZE);
00089     if (0 <= pages && 0 <= pagesize)
00090       return pages * pagesize;
00091   }
00092 #endif
00093 
00094 #if HAVE_PSTAT_GETSTATIC
00095   { /* This works on hpux11.  */
00096     struct pst_static pss;
00097     if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0))
00098       {
00099        double pages = pss.physical_memory;
00100        double pagesize = pss.page_size;
00101        if (0 <= pages && 0 <= pagesize)
00102          return pages * pagesize;
00103       }
00104   }
00105 #endif
00106 
00107 #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
00108   { /* This works on irix6. */
00109     struct rminfo realmem;
00110     if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0)
00111       {
00112        double pagesize = sysconf (_SC_PAGESIZE);
00113        double pages = realmem.physmem;
00114        if (0 <= pages && 0 <= pagesize)
00115          return pages * pagesize;
00116       }
00117   }
00118 #endif
00119 
00120 #if HAVE_GETSYSINFO && defined GSI_PHYSMEM
00121   { /* This works on Tru64 UNIX V4/5.  */
00122     int physmem;
00123 
00124     if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem),
00125                   NULL, NULL, NULL) == 1)
00126       {
00127        double kbytes = physmem;
00128 
00129        if (0 <= kbytes)
00130          return kbytes * 1024.0;
00131       }
00132   }
00133 #endif
00134 
00135 #if HAVE_SYSCTL && defined HW_PHYSMEM
00136   { /* This works on *bsd and darwin.  */
00137     unsigned int physmem;
00138     size_t len = sizeof physmem;
00139     static int mib[2] = { CTL_HW, HW_PHYSMEM };
00140 
00141     if (sysctl (mib, ARRAY_SIZE (mib), &physmem, &len, NULL, 0) == 0
00142        && len == sizeof (physmem))
00143       return (double) physmem;
00144   }
00145 #endif
00146 
00147 #if HAVE__SYSTEM_CONFIGURATION
00148   /* This works on AIX 4.3.3+.  */
00149   return _system_configuration.physmem;
00150 #endif
00151 
00152 #if defined _WIN32
00153   { /* this works on windows */
00154     PFN_MS_EX pfnex;
00155     HMODULE h = GetModuleHandle ("kernel32.dll");
00156 
00157     if (!h)
00158       return 0.0;
00159 
00160     /*  Use GlobalMemoryStatusEx if available.  */
00161     if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx")))
00162       {
00163        lMEMORYSTATUSEX lms_ex;
00164        lms_ex.dwLength = sizeof lms_ex;
00165        if (!pfnex (&lms_ex))
00166          return 0.0;
00167        return (double) lms_ex.ullTotalPhys;
00168       }
00169 
00170     /*  Fall back to GlobalMemoryStatus which is always available.
00171         but returns wrong results for physical memory > 4GB.  */
00172     else
00173       {
00174        MEMORYSTATUS ms;
00175        GlobalMemoryStatus (&ms);
00176        return (double) ms.dwTotalPhys;
00177       }
00178   }
00179 #endif
00180 
00181   /* Return 0 if we can't determine the value.  */
00182   return 0;
00183 }
00184 
00185 /* Return the amount of physical memory available.  */
00186 double
00187 physmem_available (void)
00188 {
00189 #if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE
00190   { /* This works on linux-gnu, solaris2 and cygwin.  */
00191     double pages = sysconf (_SC_AVPHYS_PAGES);
00192     double pagesize = sysconf (_SC_PAGESIZE);
00193     if (0 <= pages && 0 <= pagesize)
00194       return pages * pagesize;
00195   }
00196 #endif
00197 
00198 #if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC
00199   { /* This works on hpux11.  */
00200     struct pst_static pss;
00201     struct pst_dynamic psd;
00202     if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0)
00203        && 0 <= pstat_getdynamic (&psd, sizeof psd, 1, 0))
00204       {
00205        double pages = psd.psd_free;
00206        double pagesize = pss.page_size;
00207        if (0 <= pages && 0 <= pagesize)
00208          return pages * pagesize;
00209       }
00210   }
00211 #endif
00212 
00213 #if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
00214   { /* This works on irix6. */
00215     struct rminfo realmem;
00216     if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0)
00217       {
00218        double pagesize = sysconf (_SC_PAGESIZE);
00219        double pages = realmem.availrmem;
00220        if (0 <= pages && 0 <= pagesize)
00221          return pages * pagesize;
00222       }
00223   }
00224 #endif
00225 
00226 #if HAVE_TABLE && defined TBL_VMSTATS
00227   { /* This works on Tru64 UNIX V4/5.  */
00228     struct tbl_vmstats vmstats;
00229 
00230     if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1)
00231       {
00232        double pages = vmstats.free_count;
00233        double pagesize = vmstats.pagesize;
00234 
00235        if (0 <= pages && 0 <= pagesize)
00236          return pages * pagesize;
00237       }
00238   }
00239 #endif
00240 
00241 #if HAVE_SYSCTL && defined HW_USERMEM
00242   { /* This works on *bsd and darwin.  */
00243     unsigned int usermem;
00244     size_t len = sizeof usermem;
00245     static int mib[2] = { CTL_HW, HW_USERMEM };
00246 
00247     if (sysctl (mib, ARRAY_SIZE (mib), &usermem, &len, NULL, 0) == 0
00248        && len == sizeof (usermem))
00249       return (double) usermem;
00250   }
00251 #endif
00252 
00253 #if defined _WIN32
00254   { /* this works on windows */
00255     PFN_MS_EX pfnex;
00256     HMODULE h = GetModuleHandle ("kernel32.dll");
00257 
00258     if (!h)
00259       return 0.0;
00260 
00261     /*  Use GlobalMemoryStatusEx if available.  */
00262     if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx")))
00263       {
00264        lMEMORYSTATUSEX lms_ex;
00265        lms_ex.dwLength = sizeof lms_ex;
00266        if (!pfnex (&lms_ex))
00267          return 0.0;
00268        return (double) lms_ex.ullAvailPhys;
00269       }
00270 
00271     /*  Fall back to GlobalMemoryStatus which is always available.
00272         but returns wrong results for physical memory > 4GB  */
00273     else
00274       {
00275        MEMORYSTATUS ms;
00276        GlobalMemoryStatus (&ms);
00277        return (double) ms.dwAvailPhys;
00278       }
00279   }
00280 #endif
00281 
00282   /* Guess 25% of physical memory.  */
00283   return physmem_total () / 4;
00284 }
00285 
00286 
00287 #if DEBUG
00288 
00289 # include <stdio.h>
00290 # include <stdlib.h>
00291 
00292 int
00293 main (void)
00294 {
00295   printf ("%12.f %12.f\n", physmem_total (), physmem_available ());
00296   exit (0);
00297 }
00298 
00299 #endif /* DEBUG */
00300 
00301 /*
00302 Local Variables:
00303 compile-command: "gcc -DDEBUG -DHAVE_CONFIG_H -I.. -g -O -Wall -W physmem.c"
00304 End:
00305 */