Back to index

lshw  02.16
mem.cc
Go to the documentation of this file.
00001 /*
00002  * mem.cc
00003  *
00004  * This scan tries to guess the size of system memory by looking at several
00005  * sources:
00006  * - the size of /proc/kcore
00007  * - the value returned by the sysconf libc function
00008  * - the sum of sizes of individual memory banks
00009  *
00010  * NOTE: Except in last case, this guess can be widely inaccurate, as the
00011  * kernel itself limits the memory addressable by userspace processes.
00012  * Because of that, this module reports the biggest value found if it can't
00013  * access the size of individual memory banks (information filled in by other
00014  * scans like DMI (on PCs) or OpenFirmare device-tree (on Macs).
00015  *
00016  */
00017 
00018 #include "version.h"
00019 #include "config.h"
00020 #include "mem.h"
00021 #include <sys/types.h>
00022 #include <sys/stat.h>
00023 #include <fcntl.h>
00024 #include <unistd.h>
00025 
00026 __ID("@(#) $Id: mem.cc 2433 2012-01-10 22:01:30Z lyonel $");
00027 
00028 static unsigned long long get_kcore_size()
00029 {
00030   struct stat buf;
00031 
00032   if (stat("/proc/kcore", &buf) != 0)
00033     return 0;
00034   else
00035     return buf.st_size;
00036 }
00037 
00038 
00039 static unsigned long long get_sysconf_size()
00040 {
00041   long pagesize = 0;
00042   long physpages = 0;
00043   unsigned long long logicalmem = 0;
00044 
00045   pagesize = sysconf(_SC_PAGESIZE);
00046   physpages = sysconf(_SC_PHYS_PAGES);
00047   if ((pagesize > 0) && (physpages > 0))
00048     logicalmem =
00049       (unsigned long long) pagesize *(unsigned long long) physpages;
00050 
00051   return logicalmem;
00052 }
00053 
00054 
00055 static unsigned long long count_memorybanks_size(hwNode & n)
00056 {
00057   hwNode *memory = n.getChild("core/memory");
00058 
00059   if (memory)
00060   {
00061     unsigned long long size = 0;
00062 
00063     memory->claim(true);                          // claim memory and all its children
00064 
00065     for (unsigned int i = 0; i < memory->countChildren(); i++)
00066       if (memory->getChild(i)->getClass() == hw::memory)
00067         size += memory->getChild(i)->getSize();
00068 
00069     memory->setSize(size);
00070     return size;
00071   }
00072   else
00073     return 0;
00074 }
00075 
00076 
00077 static void claim_memory(hwNode & n)
00078 {
00079   hwNode *core = n.getChild("core");
00080 
00081   if (core)
00082   {
00083     for (unsigned int i = 0; i < core->countChildren(); i++)
00084       if (core->getChild(i)->getClass() == hw::memory)
00085         if(core->getChild(i)->claimed())
00086           core->getChild(i)->claim(true);         // claim memory and all its children
00087   }
00088 }
00089 
00090 
00091 bool scan_memory(hwNode & n)
00092 {
00093   hwNode *memory = n.getChild("core/memory");
00094   unsigned long long logicalmem = 0;
00095   unsigned long long kcore = 0;
00096 
00097   logicalmem = get_sysconf_size();
00098   kcore = get_kcore_size();
00099   count_memorybanks_size(n);
00100   claim_memory(n);
00101 
00102   if (!memory)
00103   {
00104     hwNode *core = n.getChild("core");
00105 
00106     if (!core)
00107     {
00108       n.addChild(hwNode("core", hw::bus));
00109       core = n.getChild("core");
00110     }
00111 
00112     if (core)
00113     {
00114       core->addChild(hwNode("memory", hw::memory));
00115       memory = core->getChild("memory");
00116     }
00117   }
00118 
00119   if (memory)
00120   {
00121     memory->claim();
00122     memory->addHint("icon", string("memory"));
00123 
00124     if (memory->getDescription() == "")
00125       memory->setDescription(_("System memory"));
00126 
00127     if (memory->getSize() > logicalmem)           // we already have a value
00128       return true;
00129 
00130     if ((logicalmem == 0)
00131       || ((kcore > logicalmem) && (kcore < 2 * logicalmem)))
00132       memory->setSize(kcore);
00133     else
00134       memory->setSize(logicalmem);
00135 
00136     return true;
00137   }
00138 
00139   return false;
00140 }