# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

system_info.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "stdmisc.h"
00027 
00028 #ifdef NL_OS_WINDOWS
00029 #include <windows.h>
00030 #include <tchar.h>
00031 #else
00032 #include <sys/types.h>
00033 #include <sys/stat.h>
00034 #include <fcntl.h>
00035 #include <unistd.h>
00036 #endif
00037 
00038 #include "nel/misc/system_info.h"
00039 #include "nel/misc/command.h"
00040 #include "nel/misc/heap_allocator.h"
00041 
00042 using namespace std;
00043 
00044 namespace NLMISC {
00045 
00046 string CSystemInfo::getOS ()
00047 {
00048         string OSString = "Unknown";
00049 #ifdef NL_OS_WINDOWS
00050         char ver[1024];
00051 
00052         OSVERSIONINFOEX osvi;
00053         BOOL bOsVersionInfoEx;
00054 
00055         // Try calling GetVersionEx using the OSVERSIONINFOEX structure,
00056         // which is supported on Windows 2000.
00057         //
00058         // If that fails, try using the OSVERSIONINFO structure.
00059 
00060         ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
00061         osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
00062 
00063         if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
00064         {
00065                 // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
00066                 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
00067                 if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) 
00068                         return "Windows Unknown";
00069         }
00070 
00071         switch (osvi.dwPlatformId)
00072         {
00073         case VER_PLATFORM_WIN32_NT:
00074                 // Test for the product.
00075 
00076                 if ( osvi.dwMajorVersion <= 4 )
00077                         OSString = "Microsoft Windows NT ";
00078 
00079                 if ( osvi.dwMajorVersion == 5 )
00080                         OSString = "Microsoft Windows 2000 ";
00081 
00082                 // Test for workstation versus server.
00083 /* can't access to product type
00084                 if( bOsVersionInfoEx )
00085                 {
00086                         if ( osvi.wProductType == VER_NT_WORKSTATION )
00087                         OSString += "Professional ";
00088 
00089                         if ( osvi.wProductType == VER_NT_SERVER )
00090                         OSString += "Server ";
00091                 }
00092                 else
00093 */              {
00094                         HKEY hKey;
00095                         char szProductType[80];
00096                         DWORD dwBufLen;
00097 
00098                         RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hKey );
00099                         RegQueryValueEx( hKey, "ProductType", NULL, NULL, (LPBYTE) szProductType, &dwBufLen);
00100                         RegCloseKey( hKey );
00101                         if ( lstrcmpi( "WINNT", szProductType) == 0 )
00102                                 OSString += "Workstation ";
00103                         if ( lstrcmpi( "SERVERNT", szProductType) == 0 )
00104                                 OSString += "Server ";
00105                 }
00106 
00107                 // Display version, service pack (if any), and build number.
00108                 smprintf(ver, 1024, "version %d.%d '%s' (Build %d)", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
00109                 OSString += ver;
00110                 break;
00111 
00112         case VER_PLATFORM_WIN32_WINDOWS:
00113 
00114                 if(osvi.dwMinorVersion == 0)
00115                         OSString = "Microsoft Windows 95 ";
00116                 else if (osvi.dwMinorVersion == 10)
00117                         OSString = "Microsoft Windows 98 ";
00118                 else if (osvi.dwMinorVersion == 90)
00119                         OSString = "Microsoft Windows Millenium ";
00120 /* microsoft way
00121                 if ((osvi.dwMajorVersion > 4) || (osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion > 0)))
00122                         OSString += "Microsoft Windows 98 ";
00123                 else
00124                         OSString += "Microsoft Windows 95 ";
00125 */
00126                 // Display version, service pack (if any), and build number.
00127                 smprintf(ver, 1024, "version %d.%d %s (Build %d)", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
00128                 OSString += ver;
00129                 break;
00130 
00131         case VER_PLATFORM_WIN32s:
00132                 OSString = "Microsoft Win32s";
00133                 break;
00134         }
00135 
00136 #elif defined NL_OS_UNIX
00137 
00138         OSString = "Unix";
00139 
00140 #endif  // NL_OS_UNIX
00141 
00142         return OSString;
00143 }
00144 
00145 string CSystemInfo::getProc ()
00146 {
00147         string ProcString = "Unknown";
00148 
00149 #ifdef NL_OS_WINDOWS
00150 
00151         LONG result;
00152         char value[1024];
00153         DWORD valueSize;
00154         HKEY hKey;
00155 
00156         result = ::RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Hardware\\Description\\System\\CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey);
00157         if (result == ERROR_SUCCESS)
00158         {
00159                 // get processor name
00160                 valueSize = 1024;
00161                 result = ::RegQueryValueEx (hKey, _T("ProcessorNameString"), NULL, NULL, (LPBYTE)&value, &valueSize);
00162                 if (result == ERROR_SUCCESS)
00163                         ProcString = value;
00164                 else
00165                         ProcString = "UnknownProc";
00166 
00167                 ProcString += " / ";
00168 
00169                 // get processor identifier
00170                 valueSize = 1024;
00171                 result = ::RegQueryValueEx (hKey, _T("Identifier"), NULL, NULL, (LPBYTE)&value, &valueSize);
00172                 if (result == ERROR_SUCCESS)
00173                         ProcString += value;
00174                 else
00175                         ProcString += "UnknownIdentifier";
00176 
00177                 ProcString += " / ";
00178 
00179                 // get processor vendor
00180                 valueSize = 1024;
00181                 result = ::RegQueryValueEx (hKey, _T("VendorIdentifier"), NULL, NULL, (LPBYTE)&value, &valueSize);
00182                 if (result == ERROR_SUCCESS)
00183                         ProcString += value;
00184                 else
00185                         ProcString += "UnknownVendor";
00186 
00187                 ProcString += " / ";
00188                 
00189                 // get processor frequence
00190                 result = ::RegQueryValueEx (hKey, _T("~MHz"), NULL, NULL, (LPBYTE)&value, &valueSize);
00191                 if (result == ERROR_SUCCESS)
00192                 {
00193                         ProcString += itoa (*(int *)value, value, 10);
00194                         ProcString += "MHz";
00195                 }
00196                 else
00197                         ProcString += "UnknownFreq";
00198         }
00199 
00200         // Make sure to close the reg key
00201 
00202         RegCloseKey (hKey);
00203 
00204 #elif defined NL_OS_UNIX
00205 
00206 
00207 #endif
00208 
00209         return ProcString;
00210 }
00211 
00212 string CSystemInfo::getMem ()
00213 {
00214         string MemString = "Unknown";
00215 
00216 #ifdef NL_OS_WINDOWS
00217 
00218         MEMORYSTATUS ms;
00219 
00220         GlobalMemoryStatus (&ms);
00221 
00222         sint extt = 0, extf = 0;
00223         char *ext2str[] = { "b", "Kb", "Mb", "Gb", "Tb" };
00224 
00225         while (ms.dwTotalPhys > 1024)
00226         {
00227                 ms.dwTotalPhys /= 1024;
00228                 extt++;
00229         }
00230         
00231         while (ms.dwAvailPhys > 1024)
00232         {
00233                 ms.dwAvailPhys /= 1024;
00234                 extf++;
00235         }
00236 
00237         char mem[1024];
00238         smprintf (mem, 1024, "physical memory: total: %d %s free: %d %s", ms.dwTotalPhys+1, ext2str[extt], ms.dwAvailPhys+1, ext2str[extf]);
00239         MemString = mem;
00240 
00241 #elif defined NL_OS_UNIX
00242 
00243 
00244 #endif
00245 
00246         return MemString;
00247 }
00248 
00249 
00250 static bool DetectMMX()
00251 {               
00252         #ifdef NL_OS_WINDOWS            
00253                 if (!CSystemInfo::hasCPUID()) return false; // cpuid not supported ...
00254 
00255                 uint32 result = 0;
00256                 __asm
00257                 {
00258                          mov  eax,1
00259                          cpuid
00260                          test edx,0x800000  // bit 23 = MMX instruction set
00261                          je   noMMX
00262                          mov result, 1  
00263                         noMMX:
00264                 }
00265 
00266                 return result == 1;
00267  
00268                 // printf("mmx detected\n");
00269 
00270         #else
00271                 return false;
00272         #endif
00273 }
00274 
00275 
00276 static bool DetectSSE()
00277 {       
00278         #ifdef NL_OS_WINDOWS
00279                 if (!CSystemInfo::hasCPUID()) return false; // cpuid not supported ...
00280 
00281                 uint32 result = 0;
00282                 __asm
00283                 {                       
00284                         mov eax, 1   // request for feature flags
00285                         cpuid                                                   
00286                         test EDX, 002000000h   // bit 25 in feature flags equal to 1
00287                         je noSSE
00288                         mov result, 1  // sse detected
00289                 noSSE:
00290                 }
00291 
00292 
00293                 if (result)
00294                 {
00295                         // check OS support for SSE
00296                         try 
00297                         {
00298                                 __asm
00299                                 {
00300                                         xorps xmm0, xmm0  // Streaming SIMD Extension
00301                                 }
00302                         }
00303                         catch(...)
00304                         {
00305                                 return false;
00306                         }
00307                 
00308                         // printf("sse detected\n");
00309 
00310                         return true;
00311                 }
00312                 else
00313                 {
00314                         return false;
00315                 }
00316         #else
00317                 return false;
00318         #endif
00319 }
00320 
00321 static bool HaveMMX = DetectMMX ();
00322 static bool HaveSSE = DetectSSE ();
00323 
00324 bool CSystemInfo::hasCPUID ()
00325 {
00326         #ifdef NL_OS_WINDOWS
00327                  uint32 result;
00328                  __asm
00329                  {
00330                          pushad
00331                          pushfd
00332                          //      If ID bit of EFLAGS can change, then cpuid is available
00333                          pushfd
00334                          pop  eax                                       // Get EFLAG
00335                          mov  ecx,eax
00336                          xor  eax,0x200000                      // Flip ID bit
00337                          push eax
00338                          popfd                                          // Write EFLAGS
00339                          pushfd      
00340                          pop  eax                                       // read back EFLAG
00341                          xor  eax,ecx
00342                          je   noCpuid                           // no flip -> no CPUID instr.
00343                          
00344                          popfd                                          // restore state
00345                          popad
00346                          mov  result, 1
00347                          jmp  CPUIDPresent
00348                 
00349                         noCpuid:
00350                          popfd                                      // restore state
00351                          popad
00352                          mov result, 0
00353                         CPUIDPresent:
00354                  }
00355                  return result == 1;
00356         #else
00357                  return false;
00358         #endif
00359 }
00360 bool CSystemInfo::hasMMX () { return HaveMMX; }
00361 bool CSystemInfo::hasSSE () { return HaveSSE; }
00362 
00363 
00364 bool CSystemInfo::isNT()
00365 {
00366 #ifdef NL_OS_WINDOWS
00367         OSVERSIONINFO ver;
00368         ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00369         GetVersionEx(&ver);
00370         return ver.dwPlatformId == VER_PLATFORM_WIN32_NT;
00371 #else
00372         return false;
00373 #endif
00374 }
00375 
00376 
00377 #ifdef NL_OS_UNIX
00378 
00379 static inline char *skipWS(const char *p)
00380 {
00381     while (isspace(*p)) p++;
00382     return (char *)p;
00383 }
00384 
00385 static inline char *skipToken(const char *p)
00386 {
00387     while (isspace(*p)) p++;
00388     while (*p && !isspace(*p)) p++;
00389     return (char *)p;
00390 }
00391 
00392 // col: 0=total used free shared buffers cached
00393 uint32 getSystemMemory (uint col)
00394 {
00395         if (col > 5)
00396                 return 0;
00397 
00398     char buffer[4096+1];
00399     int fd, len;
00400     char *p;
00401         
00402     /* get system wide memory usage */
00403     {
00404                 char *p;
00405                 
00406                 fd = open("/proc/meminfo", O_RDONLY);
00407                 len = read(fd, buffer, sizeof(buffer)-1);
00408                 close(fd);
00409                 buffer[len] = '\0';
00410                 
00411                 /* be prepared for extra columns to appear be seeking
00412                 to ends of lines */
00413                 p = strchr(buffer, '\n');
00414                 p = skipToken(p);                       /* "Mem:" */
00415                 for (uint i = 0; i < col; i++)
00416                 {
00417                         p = skipToken(p);
00418                 }
00419                 return strtoul(p, &p, 10);
00420         }
00421 }
00422 
00423 #endif // NL_OS_UNIX
00424 
00425 
00426 
00427 
00428 uint32 CSystemInfo::availablePhysicalMemory ()
00429 {
00430 #ifdef NL_OS_WINDOWS
00431 
00432         MEMORYSTATUS ms;
00433         GlobalMemoryStatus (&ms);
00434         return ms.dwAvailPhys;
00435 
00436 #elif defined NL_OS_UNIX
00437 
00438         return getSystemMemory (2);
00439 
00440 #endif
00441 
00442         return 0;
00443 }
00444 
00445 uint32 CSystemInfo::totalPhysicalMemory ()
00446 {
00447 #ifdef NL_OS_WINDOWS
00448 
00449         MEMORYSTATUS ms;
00450         GlobalMemoryStatus (&ms);
00451         return ms.dwTotalPhys;
00452 
00453 #elif defined NL_OS_UNIX
00454 
00455         return getSystemMemory (0);
00456         
00457 #endif
00458 
00459         return 0;
00460 }
00461 
00462 
00463 NLMISC_DYNVARIABLE(uint32, AvailablePhysicalMemory, "Physical memory available on this computer in bytes")
00464 {
00465         if (get) *pointer = CSystemInfo::availablePhysicalMemory ();
00466 }
00467 
00468 NLMISC_DYNVARIABLE(uint32, TotalPhysicalMemory, "Total physical memory on this computer in bytes")
00469 {
00470         if (get) *pointer = CSystemInfo::totalPhysicalMemory ();
00471 }
00472 
00473 NLMISC_DYNVARIABLE(uint32, ProcessUsedMemory, "Memory used by this process in bytes")
00474 {
00475         if (get) *pointer = CHeapAllocator::getAllocatedSystemMemory ();
00476 }
00477 
00478 
00479 } // NLMISC