llsys.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:22k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llsys.cpp
  3.  * @brief Impelementation of the basic system query functions.
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "llsys.h"
  34. #include <iostream>
  35. #ifdef LL_STANDALONE
  36. # include <zlib.h>
  37. #else
  38. # include "zlib/zlib.h"
  39. #endif
  40. #include "llprocessor.h"
  41. #if LL_WINDOWS
  42. # define WIN32_LEAN_AND_MEAN
  43. # include <winsock2.h>
  44. # include <windows.h>
  45. #elif LL_DARWIN
  46. # include <errno.h>
  47. # include <sys/sysctl.h>
  48. # include <sys/utsname.h>
  49. # include <stdint.h>
  50. #elif LL_LINUX
  51. # include <errno.h>
  52. # include <sys/utsname.h>
  53. # include <unistd.h>
  54. # include <sys/sysinfo.h>
  55. const char MEMINFO_FILE[] = "/proc/meminfo";
  56. const char CPUINFO_FILE[] = "/proc/cpuinfo";
  57. #elif LL_SOLARIS
  58. # include <stdio.h>
  59. # include <unistd.h>
  60. # include <sys/utsname.h>
  61. # define _STRUCTURED_PROC 1
  62. # include <sys/procfs.h>
  63. # include <sys/types.h>
  64. # include <sys/stat.h>
  65. # include <fcntl.h>
  66. # include <errno.h>
  67. extern int errno;
  68. #endif
  69. static const S32 CPUINFO_BUFFER_SIZE = 16383;
  70. LLCPUInfo gSysCPU;
  71. #if LL_WINDOWS
  72. #ifndef DLLVERSIONINFO
  73. typedef struct _DllVersionInfo
  74. {
  75.     DWORD cbSize;
  76.     DWORD dwMajorVersion;
  77.     DWORD dwMinorVersion;
  78.     DWORD dwBuildNumber;
  79.     DWORD dwPlatformID;
  80. }DLLVERSIONINFO;
  81. #endif
  82. #ifndef DLLGETVERSIONPROC
  83. typedef int (FAR WINAPI *DLLGETVERSIONPROC) (DLLVERSIONINFO *);
  84. #endif
  85. bool get_shell32_dll_version(DWORD& major, DWORD& minor, DWORD& build_number)
  86. {
  87. bool result = false;
  88. const U32 BUFF_SIZE = 32767;
  89. WCHAR tempBuf[BUFF_SIZE];
  90. if(GetSystemDirectory((LPWSTR)&tempBuf, BUFF_SIZE))
  91. {
  92. std::basic_string<WCHAR> shell32_path(tempBuf);
  93. // Shell32.dll contains the DLLGetVersion function. 
  94. // according to msdn its not part of the API
  95. // so you have to go in and get it.
  96. // http://msdn.microsoft.com/en-us/library/bb776404(VS.85).aspx
  97. shell32_path += TEXT("\shell32.dll");
  98. HMODULE hDllInst = LoadLibrary(shell32_path.c_str());   //load the DLL
  99. if(hDllInst) 
  100. {  // Could successfully load the DLL
  101. DLLGETVERSIONPROC pDllGetVersion;
  102. /*
  103. You must get this function explicitly because earlier versions of the DLL
  104. don't implement this function. That makes the lack of implementation of the
  105. function a version marker in itself.
  106. */
  107. pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hDllInst, 
  108. "DllGetVersion");
  109. if(pDllGetVersion) 
  110. {    
  111. // DLL supports version retrieval function
  112. DLLVERSIONINFO    dvi;
  113. ZeroMemory(&dvi, sizeof(dvi));
  114. dvi.cbSize = sizeof(dvi);
  115. HRESULT hr = (*pDllGetVersion)(&dvi);
  116. if(SUCCEEDED(hr)) 
  117. { // Finally, the version is at our hands
  118. major = dvi.dwMajorVersion;
  119. minor = dvi.dwMinorVersion;
  120. build_number = dvi.dwBuildNumber;
  121. result = true;
  122. FreeLibrary(hDllInst);  // Release DLL
  123. }
  124. return result;
  125. }
  126. #endif // LL_WINDOWS
  127. LLOSInfo::LLOSInfo() :
  128. mMajorVer(0), mMinorVer(0), mBuild(0)
  129. {
  130. #if LL_WINDOWS
  131. OSVERSIONINFOEX osvi;
  132. BOOL bOsVersionInfoEx;
  133. // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
  134. ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
  135. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  136. if(!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osvi)))
  137. {
  138. // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
  139. osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  140. if(!GetVersionEx( (OSVERSIONINFO *) &osvi))
  141. return;
  142. }
  143. mMajorVer = osvi.dwMajorVersion;
  144. mMinorVer = osvi.dwMinorVersion;
  145. mBuild = osvi.dwBuildNumber;
  146. DWORD shell32_major, shell32_minor, shell32_build;
  147. bool got_shell32_version = get_shell32_dll_version(shell32_major, 
  148.    shell32_minor, 
  149.    shell32_build);
  150. switch(osvi.dwPlatformId)
  151. {
  152. case VER_PLATFORM_WIN32_NT:
  153. {
  154. // Test for the product.
  155. if(osvi.dwMajorVersion <= 4)
  156. {
  157. mOSStringSimple = "Microsoft Windows NT ";
  158. }
  159. else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
  160. {
  161. mOSStringSimple = "Microsoft Windows 2000 ";
  162. }
  163. else if(osvi.dwMajorVersion ==5 && osvi.dwMinorVersion == 1)
  164. {
  165. mOSStringSimple = "Microsoft Windows XP ";
  166. }
  167. else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
  168. {
  169.  if(osvi.wProductType == VER_NT_WORKSTATION)
  170. mOSStringSimple = "Microsoft Windows XP x64 Edition ";
  171.  else
  172.  mOSStringSimple = "Microsoft Windows Server 2003 ";
  173. }
  174. else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion <= 1)
  175. {
  176. if(osvi.dwMinorVersion == 0)
  177. {
  178. mOSStringSimple = "Microsoft Windows Vista ";
  179. }
  180. else if(osvi.dwMinorVersion == 1)
  181. {
  182. mOSStringSimple = "Microsoft Windows 7 ";
  183. }
  184. if(osvi.wProductType != VER_NT_WORKSTATION)
  185. {
  186. mOSStringSimple += "Server ";
  187. }
  188. ///get native system info if available..
  189. typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); ///function pointer for loading GetNativeSystemInfo
  190. SYSTEM_INFO si; //System Info object file contains architecture info
  191. PGNSI pGNSI; //pointer object
  192. ZeroMemory(&si, sizeof(SYSTEM_INFO)); //zero out the memory in information
  193. pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),  "GetNativeSystemInfo"); //load kernel32 get function
  194. if(NULL != pGNSI) //check if it has failed
  195. pGNSI(&si); //success
  196. else 
  197. GetSystemInfo(&si); //if it fails get regular system info 
  198. //(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
  199. //msdn microsoft finds 32 bit and 64 bit flavors this way..
  200. //http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors
  201. //of windows than this code does (in case it is needed for the future)
  202. if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 ) //check for 64 bit
  203. {
  204. mOSStringSimple += "64-bit ";
  205. }
  206. else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
  207. {
  208. mOSStringSimple += "32-bit ";
  209. }
  210. }
  211. else   // Use the registry on early versions of Windows NT.
  212. {
  213. mOSStringSimple = "Microsoft Windows (unrecognized) ";
  214. HKEY hKey;
  215. WCHAR szProductType[80];
  216. DWORD dwBufLen;
  217. RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  218. L"SYSTEM\CurrentControlSet\Control\ProductOptions",
  219. 0, KEY_QUERY_VALUE, &hKey );
  220. RegQueryValueEx( hKey, L"ProductType", NULL, NULL,
  221. (LPBYTE) szProductType, &dwBufLen);
  222. RegCloseKey( hKey );
  223. if ( lstrcmpi( L"WINNT", szProductType) == 0 )
  224. {
  225. mOSStringSimple += "Professional ";
  226. }
  227. else if ( lstrcmpi( L"LANMANNT", szProductType) == 0 )
  228. {
  229. mOSStringSimple += "Server ";
  230. }
  231. else if ( lstrcmpi( L"SERVERNT", szProductType) == 0 )
  232. {
  233. mOSStringSimple += "Advanced Server ";
  234. }
  235. }
  236. std::string csdversion = utf16str_to_utf8str(osvi.szCSDVersion);
  237. // Display version, service pack (if any), and build number.
  238. std::string tmpstr;
  239. if(osvi.dwMajorVersion <= 4)
  240. {
  241. tmpstr = llformat("version %d.%d %s (Build %d)",
  242.   osvi.dwMajorVersion,
  243.   osvi.dwMinorVersion,
  244.   csdversion.c_str(),
  245.   (osvi.dwBuildNumber & 0xffff));
  246. }
  247. else
  248. {
  249. tmpstr = llformat("%s (Build %d)",
  250.   csdversion.c_str(),
  251.   (osvi.dwBuildNumber & 0xffff));
  252. }
  253. mOSString = mOSStringSimple + tmpstr;
  254. }
  255. break;
  256. case VER_PLATFORM_WIN32_WINDOWS:
  257. // Test for the Windows 95 product family.
  258. if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
  259. {
  260. mOSStringSimple = "Microsoft Windows 95 ";
  261. if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
  262. {
  263.                 mOSStringSimple += "OSR2 ";
  264. }
  265. if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
  266. {
  267. mOSStringSimple = "Microsoft Windows 98 ";
  268. if ( osvi.szCSDVersion[1] == 'A' )
  269. {
  270.                 mOSStringSimple += "SE ";
  271. }
  272. if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
  273. {
  274. mOSStringSimple = "Microsoft Windows Millennium Edition ";
  275. }
  276. mOSString = mOSStringSimple;
  277. break;
  278. }
  279. std::string compatibility_mode;
  280. if(got_shell32_version)
  281. {
  282. if(osvi.dwMajorVersion != shell32_major 
  283. || osvi.dwMinorVersion != shell32_minor)
  284. {
  285. compatibility_mode = llformat(" compatibility mode. real ver: %d.%d (Build %d)", 
  286. shell32_major,
  287. shell32_minor,
  288. shell32_build);
  289. }
  290. }
  291. mOSString += compatibility_mode;
  292. #else
  293. struct utsname un;
  294. if(uname(&un) != -1)
  295. {
  296. mOSStringSimple.append(un.sysname);
  297. mOSStringSimple.append(" ");
  298. mOSStringSimple.append(un.release);
  299. mOSString = mOSStringSimple;
  300. mOSString.append(" ");
  301. mOSString.append(un.version);
  302. mOSString.append(" ");
  303. mOSString.append(un.machine);
  304. // Simplify 'Simple'
  305. std::string ostype = mOSStringSimple.substr(0, mOSStringSimple.find_first_of(" ", 0));
  306. if (ostype == "Darwin")
  307. {
  308. // Only care about major Darwin versions, truncate at first '.'
  309. S32 idx1 = mOSStringSimple.find_first_of(".", 0);
  310. std::string simple = mOSStringSimple.substr(0, idx1);
  311. if (simple.length() > 0)
  312. mOSStringSimple = simple;
  313. }
  314. else if (ostype == "Linux")
  315. {
  316. // Only care about major and minor Linux versions, truncate at second '.'
  317. std::string::size_type idx1 = mOSStringSimple.find_first_of(".", 0);
  318. std::string::size_type idx2 = (idx1 != std::string::npos) ? mOSStringSimple.find_first_of(".", idx1+1) : std::string::npos;
  319. std::string simple = mOSStringSimple.substr(0, idx2);
  320. if (simple.length() > 0)
  321. mOSStringSimple = simple;
  322. }
  323. }
  324. else
  325. {
  326. mOSStringSimple.append("Unable to collect OS info");
  327. mOSString = mOSStringSimple;
  328. }
  329. #endif
  330. }
  331. #ifndef LL_WINDOWS
  332. // static
  333. S32 LLOSInfo::getMaxOpenFiles()
  334. {
  335. const S32 OPEN_MAX_GUESS = 256;
  336. #ifdef OPEN_MAX
  337. static S32 open_max = OPEN_MAX;
  338. #else
  339. static S32 open_max = 0;
  340. #endif
  341. if (0 == open_max)
  342. {
  343. // First time through.
  344. errno = 0;
  345. if ( (open_max = sysconf(_SC_OPEN_MAX)) < 0)
  346. {
  347. if (0 == errno)
  348. {
  349. // Indeterminate.
  350. open_max = OPEN_MAX_GUESS;
  351. }
  352. else
  353. {
  354. llerrs << "LLOSInfo::getMaxOpenFiles: sysconf error for _SC_OPEN_MAX" << llendl;
  355. }
  356. }
  357. }
  358. return open_max;
  359. }
  360. #endif
  361. void LLOSInfo::stream(std::ostream& s) const
  362. {
  363. s << mOSString;
  364. }
  365. const std::string& LLOSInfo::getOSString() const
  366. {
  367. return mOSString;
  368. }
  369. const std::string& LLOSInfo::getOSStringSimple() const
  370. {
  371. return mOSStringSimple;
  372. }
  373. const S32 STATUS_SIZE = 8192;
  374. //static
  375. U32 LLOSInfo::getProcessVirtualSizeKB()
  376. {
  377. U32 virtual_size = 0;
  378. #if LL_WINDOWS
  379. #endif
  380. #if LL_LINUX
  381. LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb");
  382. if (status_filep)
  383. {
  384. S32 numRead = 0;
  385. char buff[STATUS_SIZE]; /* Flawfinder: ignore */
  386. size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep);
  387. buff[nbytes] = '';
  388. // All these guys return numbers in KB
  389. char *memp = strstr(buff, "VmSize:");
  390. if (memp)
  391. {
  392. numRead += sscanf(memp, "%*s %u", &virtual_size);
  393. }
  394. fclose(status_filep);
  395. }
  396. #elif LL_SOLARIS
  397. char proc_ps[LL_MAX_PATH];
  398. sprintf(proc_ps, "/proc/%d/psinfo", (int)getpid());
  399. int proc_fd = -1;
  400. if((proc_fd = open(proc_ps, O_RDONLY)) == -1){
  401. llwarns << "unable to open " << proc_ps << llendl;
  402. return 0;
  403. }
  404. psinfo_t proc_psinfo;
  405. if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
  406. llwarns << "Unable to read " << proc_ps << llendl;
  407. close(proc_fd);
  408. return 0;
  409. }
  410. close(proc_fd);
  411. virtual_size = proc_psinfo.pr_size;
  412. #endif
  413. return virtual_size;
  414. }
  415. //static
  416. U32 LLOSInfo::getProcessResidentSizeKB()
  417. {
  418. U32 resident_size = 0;
  419. #if LL_WINDOWS
  420. #endif
  421. #if LL_LINUX
  422. LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb");
  423. if (status_filep != NULL)
  424. {
  425. S32 numRead = 0;
  426. char buff[STATUS_SIZE]; /* Flawfinder: ignore */
  427. size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep);
  428. buff[nbytes] = '';
  429. // All these guys return numbers in KB
  430. char *memp = strstr(buff, "VmRSS:");
  431. if (memp)
  432. {
  433. numRead += sscanf(memp, "%*s %u", &resident_size);
  434. }
  435. fclose(status_filep);
  436. }
  437. #elif LL_SOLARIS
  438. char proc_ps[LL_MAX_PATH];
  439. sprintf(proc_ps, "/proc/%d/psinfo", (int)getpid());
  440. int proc_fd = -1;
  441. if((proc_fd = open(proc_ps, O_RDONLY)) == -1){
  442. llwarns << "unable to open " << proc_ps << llendl;
  443. return 0;
  444. }
  445. psinfo_t proc_psinfo;
  446. if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
  447. llwarns << "Unable to read " << proc_ps << llendl;
  448. close(proc_fd);
  449. return 0;
  450. }
  451. close(proc_fd);
  452. resident_size = proc_psinfo.pr_rssize;
  453. #endif
  454. return resident_size;
  455. }
  456. LLCPUInfo::LLCPUInfo()
  457. {
  458. std::ostringstream out;
  459. CProcessor proc;
  460. const ProcessorInfo* info = proc.GetCPUInfo();
  461. // proc.WriteInfoTextFile("procInfo.txt");
  462. mHasSSE = info->_Ext.SSE_StreamingSIMD_Extensions;
  463. mHasSSE2 = info->_Ext.SSE2_StreamingSIMD2_Extensions;
  464. mHasAltivec = info->_Ext.Altivec_Extensions;
  465. mCPUMhz = (S32)(proc.GetCPUFrequency(50)/1000000.0);
  466. mFamily.assign( info->strFamily );
  467. mCPUString = "Unknown";
  468. #if LL_WINDOWS || LL_DARWIN || LL_SOLARIS
  469. out << proc.strCPUName;
  470. if (200 < mCPUMhz && mCPUMhz < 10000)           // *NOTE: cpu speed is often way wrong, do a sanity check
  471. {
  472. out << " (" << mCPUMhz << " MHz)";
  473. }
  474. mCPUString = out.str();
  475. #elif LL_LINUX
  476. std::map< std::string, std::string > cpuinfo;
  477. LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb");
  478. if(cpuinfo_fp)
  479. {
  480. char line[MAX_STRING];
  481. memset(line, 0, MAX_STRING);
  482. while(fgets(line, MAX_STRING, cpuinfo_fp))
  483. {
  484. // /proc/cpuinfo on Linux looks like:
  485. // namet*: valuen
  486. char* tabspot = strchr( line, 't' );
  487. if (tabspot == NULL)
  488. continue;
  489. char* colspot = strchr( tabspot, ':' );
  490. if (colspot == NULL)
  491. continue;
  492. char* spacespot = strchr( colspot, ' ' );
  493. if (spacespot == NULL)
  494. continue;
  495. char* nlspot = strchr( line, 'n' );
  496. if (nlspot == NULL)
  497. nlspot = line + strlen( line ); // Fallback to terminating NUL
  498. std::string linename( line, tabspot );
  499. std::string llinename(linename);
  500. LLStringUtil::toLower(llinename);
  501. std::string lineval( spacespot + 1, nlspot );
  502. cpuinfo[ llinename ] = lineval;
  503. }
  504. fclose(cpuinfo_fp);
  505. }
  506. # if LL_X86
  507. std::string flags = " " + cpuinfo["flags"] + " ";
  508. LLStringUtil::toLower(flags);
  509. mHasSSE = ( flags.find( " sse " ) != std::string::npos );
  510. mHasSSE2 = ( flags.find( " sse2 " ) != std::string::npos );
  511. F64 mhz;
  512. if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz)
  513.     && 200.0 < mhz && mhz < 10000.0)
  514. {
  515. mCPUMhz = (S32)llrint(mhz);
  516. }
  517. if (!cpuinfo["model name"].empty())
  518. mCPUString = cpuinfo["model name"];
  519. # endif // LL_X86
  520. #endif // LL_LINUX
  521. }
  522. bool LLCPUInfo::hasAltivec() const
  523. {
  524. return mHasAltivec;
  525. }
  526. bool LLCPUInfo::hasSSE() const
  527. {
  528. return mHasSSE;
  529. }
  530. bool LLCPUInfo::hasSSE2() const
  531. {
  532. return mHasSSE2;
  533. }
  534. S32 LLCPUInfo::getMhz() const
  535. {
  536. return mCPUMhz;
  537. }
  538. std::string LLCPUInfo::getCPUString() const
  539. {
  540. return mCPUString;
  541. }
  542. void LLCPUInfo::stream(std::ostream& s) const
  543. {
  544. #if LL_WINDOWS || LL_DARWIN || LL_SOLARIS
  545. // gather machine information.
  546. char proc_buf[CPUINFO_BUFFER_SIZE]; /* Flawfinder: ignore */
  547. CProcessor proc;
  548. if(proc.CPUInfoToText(proc_buf, CPUINFO_BUFFER_SIZE))
  549. {
  550. s << proc_buf;
  551. }
  552. else
  553. {
  554. s << "Unable to collect processor information" << std::endl;
  555. }
  556. #else
  557. // *NOTE: This works on linux. What will it do on other systems?
  558. LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb");
  559. if(cpuinfo)
  560. {
  561. char line[MAX_STRING];
  562. memset(line, 0, MAX_STRING);
  563. while(fgets(line, MAX_STRING, cpuinfo))
  564. {
  565. line[strlen(line)-1] = ' ';
  566. s << line;
  567. }
  568. fclose(cpuinfo);
  569. s << std::endl;
  570. }
  571. else
  572. {
  573. s << "Unable to collect processor information" << std::endl;
  574. }
  575. #endif
  576. // These are interesting as they reflect our internal view of the
  577. // CPU's attributes regardless of platform
  578. s << "->mHasSSE:     " << (U32)mHasSSE << std::endl;
  579. s << "->mHasSSE2:    " << (U32)mHasSSE2 << std::endl;
  580. s << "->mHasAltivec: " << (U32)mHasAltivec << std::endl;
  581. s << "->mCPUMhz:     " << mCPUMhz << std::endl;
  582. s << "->mCPUString:  " << mCPUString << std::endl;
  583. }
  584. LLMemoryInfo::LLMemoryInfo()
  585. {
  586. }
  587. #if LL_WINDOWS
  588. static U32 LLMemoryAdjustKBResult(U32 inKB)
  589. {
  590. // Moved this here from llfloaterabout.cpp
  591. //! bug
  592. // For some reason, the reported amount of memory is always wrong.
  593. // The original adjustment assumes it's always off by one meg, however
  594. // errors of as much as 2520 KB have been observed in the value
  595. // returned from the GetMemoryStatusEx function.  Here we keep the
  596. // original adjustment from llfoaterabout.cpp until this can be
  597. // fixed somehow.
  598. inKB += 1024;
  599. return inKB;
  600. }
  601. #endif
  602. U32 LLMemoryInfo::getPhysicalMemoryKB() const
  603. {
  604. #if LL_WINDOWS
  605. MEMORYSTATUSEX state;
  606. state.dwLength = sizeof(state);
  607. GlobalMemoryStatusEx(&state);
  608. return LLMemoryAdjustKBResult((U32)(state.ullTotalPhys >> 10));
  609. #elif LL_DARWIN
  610. // This might work on Linux as well.  Someone check...
  611. uint64_t phys = 0;
  612. int mib[2] = { CTL_HW, HW_MEMSIZE };
  613. size_t len = sizeof(phys);
  614. sysctl(mib, 2, &phys, &len, NULL, 0);
  615. return (U32)(phys >> 10);
  616. #elif LL_LINUX
  617. U64 phys = 0;
  618. phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
  619. return (U32)(phys >> 10);
  620. #elif LL_SOLARIS
  621. U64 phys = 0;
  622. phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES));
  623. return (U32)(phys >> 10);
  624. #else
  625. return 0;
  626. #endif
  627. }
  628. U32 LLMemoryInfo::getPhysicalMemoryClamped() const
  629. {
  630. // Return the total physical memory in bytes, but clamp it
  631. // to no more than U32_MAX
  632. U32 phys_kb = getPhysicalMemoryKB();
  633. if (phys_kb >= 4194304 /* 4GB in KB */)
  634. {
  635. return U32_MAX;
  636. }
  637. else
  638. {
  639. return phys_kb << 10;
  640. }
  641. }
  642. void LLMemoryInfo::stream(std::ostream& s) const
  643. {
  644. #if LL_WINDOWS
  645. MEMORYSTATUSEX state;
  646. state.dwLength = sizeof(state);
  647. GlobalMemoryStatusEx(&state);
  648. s << "Percent Memory use: " << (U32)state.dwMemoryLoad << '%' << std::endl;
  649. s << "Total Physical KB:  " << (U32)(state.ullTotalPhys/1024) << std::endl;
  650. s << "Avail Physical KB:  " << (U32)(state.ullAvailPhys/1024) << std::endl;
  651. s << "Total page KB:      " << (U32)(state.ullTotalPageFile/1024) << std::endl;
  652. s << "Avail page KB:      " << (U32)(state.ullAvailPageFile/1024) << std::endl;
  653. s << "Total Virtual KB:   " << (U32)(state.ullTotalVirtual/1024) << std::endl;
  654. s << "Avail Virtual KB:   " << (U32)(state.ullAvailVirtual/1024) << std::endl;
  655. #elif LL_DARWIN
  656. uint64_t phys = 0;
  657. size_t len = sizeof(phys);
  658. if(sysctlbyname("hw.memsize", &phys, &len, NULL, 0) == 0)
  659. {
  660. s << "Total Physical KB:  " << phys/1024 << std::endl;
  661. }
  662. else
  663. {
  664. s << "Unable to collect memory information";
  665. }
  666. #elif LL_SOLARIS
  667.         U64 phys = 0;
  668.         phys = (U64)(sysconf(_SC_PHYS_PAGES)) * (U64)(sysconf(_SC_PAGESIZE)/1024);
  669.         s << "Total Physical KB:  " << phys << std::endl;
  670. #else
  671. // *NOTE: This works on linux. What will it do on other systems?
  672. LLFILE* meminfo = LLFile::fopen(MEMINFO_FILE,"rb");
  673. if(meminfo)
  674. {
  675. char line[MAX_STRING]; /* Flawfinder: ignore */
  676. memset(line, 0, MAX_STRING);
  677. while(fgets(line, MAX_STRING, meminfo))
  678. {
  679. line[strlen(line)-1] = ' ';  /*Flawfinder: ignore*/
  680. s << line;
  681. }
  682. fclose(meminfo);
  683. }
  684. else
  685. {
  686. s << "Unable to collect memory information";
  687. }
  688. #endif
  689. }
  690. std::ostream& operator<<(std::ostream& s, const LLOSInfo& info)
  691. {
  692. info.stream(s);
  693. return s;
  694. }
  695. std::ostream& operator<<(std::ostream& s, const LLCPUInfo& info)
  696. {
  697. info.stream(s);
  698. return s;
  699. }
  700. std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info)
  701. {
  702. info.stream(s);
  703. return s;
  704. }
  705. BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile)
  706. {
  707. std::string tmpfile;
  708. const S32 UNCOMPRESS_BUFFER_SIZE = 32768;
  709. BOOL retval = FALSE;
  710. gzFile src = NULL;
  711. U8 buffer[UNCOMPRESS_BUFFER_SIZE];
  712. LLFILE *dst = NULL;
  713. S32 bytes = 0;
  714. tmpfile = dstfile + ".t";
  715. src = gzopen(srcfile.c_str(), "rb");
  716. if (! src) goto err;
  717. dst = LLFile::fopen(tmpfile, "wb"); /* Flawfinder: ignore */
  718. if (! dst) goto err;
  719. do
  720. {
  721. bytes = gzread(src, buffer, UNCOMPRESS_BUFFER_SIZE);
  722. size_t nwrit = fwrite(buffer, sizeof(U8), bytes, dst);
  723. if (nwrit < (size_t) bytes)
  724. {
  725. llwarns << "Short write on " << tmpfile << ": Wrote " << nwrit << " of " << bytes << " bytes." << llendl;
  726. goto err;
  727. }
  728. } while(gzeof(src) == 0);
  729. fclose(dst); 
  730. dst = NULL;
  731. if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */
  732. retval = TRUE;
  733. err:
  734. if (src != NULL) gzclose(src);
  735. if (dst != NULL) fclose(dst);
  736. return retval;
  737. }
  738. BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)
  739. {
  740. const S32 COMPRESS_BUFFER_SIZE = 32768;
  741. std::string tmpfile;
  742. BOOL retval = FALSE;
  743. U8 buffer[COMPRESS_BUFFER_SIZE];
  744. gzFile dst = NULL;
  745. LLFILE *src = NULL;
  746. S32 bytes = 0;
  747. tmpfile = dstfile + ".t";
  748. dst = gzopen(tmpfile.c_str(), "wb"); /* Flawfinder: ignore */
  749. if (! dst) goto err;
  750. src = LLFile::fopen(srcfile, "rb"); /* Flawfinder: ignore */
  751. if (! src) goto err;
  752. do
  753. {
  754. bytes = (S32)fread(buffer, sizeof(U8), COMPRESS_BUFFER_SIZE,src);
  755. gzwrite(dst, buffer, bytes);
  756. } while(feof(src) == 0);
  757. gzclose(dst);
  758. dst = NULL;
  759. #if LL_WINDOWS
  760. // Rename in windows needs the dstfile to not exist.
  761. LLFile::remove(dstfile);
  762. #endif
  763. if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */
  764. retval = TRUE;
  765.  err:
  766. if (src != NULL) fclose(src);
  767. if (dst != NULL) gzclose(dst);
  768. return retval;
  769. }