summaryrefslogtreecommitdiffstats
path: root/Source/kwsys/SystemInformation.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2012-10-31 20:44:00 (GMT)
committerBrad King <brad.king@kitware.com>2012-10-31 20:44:00 (GMT)
commit17fb60bb13643a0f79c815688c317f56c551ae58 (patch)
tree33710b20819640040b4cd91186dca3ac853a520d /Source/kwsys/SystemInformation.cxx
parent97c98876b715dd954b4ce744a1a86d1d14e6ab9d (diff)
parent7ae44db4b9a1b3b26f2d670135fc00324e24f348 (diff)
downloadCMake-17fb60bb13643a0f79c815688c317f56c551ae58.zip
CMake-17fb60bb13643a0f79c815688c317f56c551ae58.tar.gz
CMake-17fb60bb13643a0f79c815688c317f56c551ae58.tar.bz2
Merge branch 'upstream-kwsys' into import-KWSys-subtree
Diffstat (limited to 'Source/kwsys/SystemInformation.cxx')
-rw-r--r--Source/kwsys/SystemInformation.cxx575
1 files changed, 460 insertions, 115 deletions
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index a9efe7b..cbd1bdc 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -9,7 +9,9 @@
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
-#ifdef _WIN32
+
+#if defined(_WIN32)
+# define NOMINMAX // use our min,max
# if !defined(_WIN32_WINNT) && !(defined(_MSC_VER) && _MSC_VER < 1300)
# define _WIN32_WINNT 0x0501
# endif
@@ -54,6 +56,7 @@
#if defined(_WIN32)
# include <windows.h>
+# include <errno.h>
# if defined(KWSYS_SYS_HAS_PSAPI)
# include <psapi.h>
# endif
@@ -64,6 +67,7 @@ typedef int siginfo_t;
# include <sys/types.h>
# include <sys/time.h>
# include <sys/utsname.h> // int uname(struct utsname *buf);
+# include <sys/resource.h> // getrlimit
# include <unistd.h>
# include <signal.h>
# include <fcntl.h>
@@ -71,15 +75,15 @@ typedef int siginfo_t;
#endif
#ifdef __APPLE__
-#include <sys/sysctl.h>
-#include <mach/vm_statistics.h>
-#include <mach/host_info.h>
-#include <mach/mach.h>
-#include <mach/mach_types.h>
-#include <fenv.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
+# include <sys/sysctl.h>
+# include <mach/vm_statistics.h>
+# include <mach/host_info.h>
+# include <mach/mach.h>
+# include <mach/mach_types.h>
+# include <fenv.h>
+# include <sys/socket.h>
+# include <netdb.h>
+# include <netinet/in.h>
# if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0 >= 1050
# include <execinfo.h>
# define KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE
@@ -95,6 +99,13 @@ typedef int siginfo_t;
# include <execinfo.h>
# define KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE
# endif
+# if defined(KWSYS_CXX_HAS_RLIMIT64)
+typedef struct rlimit64 ResourceLimitType;
+# define GetResourceLimit getrlimit64
+# else
+typedef struct rlimit ResourceLimitType;
+# define GetResourceLimit getrlimit
+# endif
#elif defined( __hpux )
# include <sys/param.h>
# include <sys/pstat.h>
@@ -105,7 +116,7 @@ typedef int siginfo_t;
#endif
#ifdef __HAIKU__
-#include <OS.h>
+# include <OS.h>
#endif
#include <memory.h>
@@ -114,8 +125,38 @@ typedef int siginfo_t;
#include <string.h>
#include <ctype.h> // int isdigit(int c);
+#if defined(KWSYS_USE_LONG_LONG)
+# if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
+# define iostreamLongLong(x) (x)
+# else
+# define iostreamLongLong(x) ((long)x)
+# endif
+#elif defined(KWSYS_USE___INT64)
+# if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
+# define iostreamLongLong(x) (x)
+# else
+# define iostreamLongLong(x) ((long)x)
+# endif
+#else
+# error "No Long Long"
+#endif
+
+#if defined(KWSYS_CXX_HAS_ATOLL)
+# define atoLongLong atoll
+#else
+# if defined(KWSYS_CXX_HAS__ATOI64)
+# define atoLongLong _atoi64
+# elif defined(KWSYS_CXX_HAS_ATOL)
+# define atoLongLong atol
+# else
+# define atoLongLong atoi
+# endif
+#endif
+
namespace KWSYS_NAMESPACE
{
+template<typename T>
+T min(T a, T b){ return a<b ? a : b; }
extern "C" { typedef void (*SigAction)(int,siginfo_t*,void*); }
@@ -168,8 +209,14 @@ public:
LongLong GetProcessId();
// Retrieve memory information in kib
- LongLong GetMemoryTotal();
- LongLong GetMemoryUsed();
+ LongLong GetHostMemoryTotal();
+ LongLong GetHostMemoryAvailable(const char *envVarName);
+ LongLong GetHostMemoryUsed();
+
+ LongLong GetProcMemoryAvailable(
+ const char *hostLimitEnvVarName,
+ const char *procLimitEnvVarName);
+ LongLong GetProcMemoryUsed();
// enable/disable stack trace signal handler.
static
@@ -448,11 +495,7 @@ const char * SystemInformation::GetHostname()
kwsys_stl::string SystemInformation::GetFullyQualifiedDomainName()
{
kwsys_stl::string fqdn;
- int ierr=this->Implementation->GetFullyQualifiedDomainName(fqdn);
- if (ierr)
- {
- fqdn="localhost";
- }
+ this->Implementation->GetFullyQualifiedDomainName(fqdn);
return fqdn;
}
@@ -552,27 +595,54 @@ size_t SystemInformation::GetAvailablePhysicalMemory()
return this->Implementation->GetAvailablePhysicalMemory();
}
-kwsys_stl::string SystemInformation::GetMemoryDescription()
+kwsys_stl::string SystemInformation::GetMemoryDescription(
+ const char *hostLimitEnvVarName,
+ const char *procLimitEnvVarName)
{
kwsys_stl::ostringstream oss;
oss
- << this->GetTotalPhysicalMemory()
- << " MB physical "
- << this->GetTotalVirtualMemory()
- << " MB virtual";
-
+ << "Host Total: "
+ << iostreamLongLong(this->GetHostMemoryTotal())
+ << " KiB, Host Available: "
+ << iostreamLongLong(this->GetHostMemoryAvailable(hostLimitEnvVarName))
+ << " KiB, Process Available: "
+ << iostreamLongLong(
+ this->GetProcMemoryAvailable(hostLimitEnvVarName,procLimitEnvVarName))
+ << " KiB";
return oss.str();
}
-// Get total system RAM in units of KiB.
-SystemInformation::LongLong SystemInformation::GetMemoryTotal()
+// host memory info in units of KiB.
+SystemInformation::LongLong SystemInformation::GetHostMemoryTotal()
{
- return this->Implementation->GetMemoryTotal();
+ return this->Implementation->GetHostMemoryTotal();
}
-SystemInformation::LongLong SystemInformation::GetMemoryUsed()
+SystemInformation::LongLong
+SystemInformation::GetHostMemoryAvailable(const char *hostLimitEnvVarName)
+{
+ return this->Implementation->GetHostMemoryAvailable(hostLimitEnvVarName);
+}
+
+SystemInformation::LongLong SystemInformation::GetHostMemoryUsed()
{
- return this->Implementation->GetMemoryUsed();
+ return this->Implementation->GetHostMemoryUsed();
+}
+
+// process memory info in units of KiB.
+SystemInformation::LongLong
+SystemInformation::GetProcMemoryAvailable(
+ const char *hostLimitEnvVarName,
+ const char *procLimitEnvVarName)
+{
+ return this->Implementation->GetProcMemoryAvailable(
+ hostLimitEnvVarName,
+ procLimitEnvVarName);
+}
+
+SystemInformation::LongLong SystemInformation::GetProcMemoryUsed()
+{
+ return this->Implementation->GetProcMemoryUsed();
}
SystemInformation::LongLong SystemInformation::GetProcessId()
@@ -671,33 +741,55 @@ void SystemInformation::RunMemoryCheck()
// initial APIC ID for the processor this code is running on.
// Default value = 0xff if HT is not supported
-
-//*****************************************************************************
+// Hide implementation details in an anonymous namespace.
+namespace {
+// *****************************************************************************
+#if defined(__linux) || defined(__APPLE__)
int LoadLines(
- const char *fileName,
+ FILE *file,
kwsys_stl::vector<kwsys_stl::string> &lines)
{
// Load each line in the given file into a the vector.
int nRead=0;
const int bufSize=1024;
char buf[bufSize]={'\0'};
- kwsys_stl::ifstream file(fileName);
- if (!file.is_open())
+ while (!feof(file) && !ferror(file))
+ {
+ errno=0;
+ if (fgets(buf,bufSize,file) == 0)
+ {
+ if (ferror(file) && (errno==EINTR))
+ {
+ clearerr(file);
+ }
+ continue;
+ }
+ lines.push_back(buf);
+ ++nRead;
+ }
+ if (ferror(file))
{
return 0;
}
- while(file.good())
+ return nRead;
+}
+
+# if defined(__linux)
+// *****************************************************************************
+int LoadLines(
+ const char *fileName,
+ kwsys_stl::vector<kwsys_stl::string> &lines)
+{
+ FILE *file=fopen(fileName,"r");
+ if (file==0)
{
- file.getline(buf,bufSize);
- if (file.gcount()>1)
- {
- lines.push_back(buf);
- ++nRead;
- }
+ return 0;
}
- file.close();
+ int nRead=LoadLines(file,lines);
+ fclose(file);
return nRead;
}
+# endif
// ****************************************************************************
template<typename T>
@@ -708,17 +800,44 @@ int NameValue(
size_t nLines=lines.size();
for (size_t i=0; i<nLines; ++i)
{
- kwsys_stl::string tok;
- kwsys_stl::istringstream is(lines[i]);
- is >> tok;
- if (tok==name)
+ size_t at=lines[i].find(name);
+ if (at==kwsys_stl::string::npos)
{
- is >> value;
- return 0;
+ continue;
}
+ kwsys_stl::istringstream is(lines[i].substr(at+name.size()));
+ is >> value;
+ return 0;
}
return -1;
}
+#endif
+
+#if defined(__linux)
+// ****************************************************************************
+template<typename T>
+int GetFieldsFromFile(
+ const char *fileName,
+ const char **fieldNames,
+ T *values)
+{
+ kwsys_stl::vector<kwsys_stl::string> fields;
+ if (!LoadLines(fileName,fields))
+ {
+ return -1;
+ }
+ int i=0;
+ while (fieldNames[i]!=NULL)
+ {
+ int ierr=NameValue(fields,fieldNames[i],values[i]);
+ if (ierr)
+ {
+ return -(i+2);
+ }
+ i+=1;
+ }
+ return 0;
+}
// ****************************************************************************
template<typename T>
@@ -727,202 +846,244 @@ int GetFieldFromFile(
const char *fieldName,
T &value)
{
+ const char *fieldNames[2]={fieldName,NULL};
+ T values[1]={T(0)};
+ int ierr=GetFieldsFromFile(fileName,fieldNames,values);
+ if (ierr)
+ {
+ return ierr;
+ }
+ value=values[0];
+ return 0;
+}
+#endif
+
+// ****************************************************************************
+#if defined(__APPLE__)
+template<typename T>
+int GetFieldsFromCommand(
+ const char *command,
+ const char **fieldNames,
+ T *values)
+{
+ FILE *file=popen(command,"r");
+ if (file==0)
+ {
+ return -1;
+ }
kwsys_stl::vector<kwsys_stl::string> fields;
- if (!LoadLines(fileName,fields))
+ int nl=LoadLines(file,fields);
+ pclose(file);
+ if (nl==0)
{
return -1;
}
- int ierr=NameValue(fields,fieldName,value);
- if (ierr)
+ int i=0;
+ while (fieldNames[i]!=NULL)
{
- return -2;
+ int ierr=NameValue(fields,fieldNames[i],values[i]);
+ if (ierr)
+ {
+ return -(i+2);
+ }
+ i+=1;
}
return 0;
}
+#endif
-//*****************************************************************************
+// ****************************************************************************
+#if !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
void StacktraceSignalHandler(
int sigNo,
siginfo_t *sigInfo,
void * /*sigContext*/)
{
#if defined(__linux) || defined(__APPLE__)
- kwsys_ios::cerr << "[" << getpid() << "] ";
-
+ kwsys_ios::ostringstream oss;
+ oss
+ << "=========================================================" << kwsys_ios::endl
+ << "Process id " << getpid() << " ";
switch (sigNo)
{
case SIGFPE:
- kwsys_ios::cerr << "Caught SIGFPE ";
+ oss << "Caught SIGFPE ";
switch (sigInfo->si_code)
{
# if defined(FPE_INTDIV)
case FPE_INTDIV:
- kwsys_ios::cerr << "integer division by zero";
+ oss << "integer division by zero";
break;
# endif
# if defined(FPE_INTOVF)
case FPE_INTOVF:
- kwsys_ios::cerr << "integer overflow";
+ oss << "integer overflow";
break;
# endif
case FPE_FLTDIV:
- kwsys_ios::cerr << "floating point divide by zero";
+ oss << "floating point divide by zero";
break;
case FPE_FLTOVF:
- kwsys_ios::cerr << "floating point overflow";
+ oss << "floating point overflow";
break;
case FPE_FLTUND:
- kwsys_ios::cerr << "floating point underflow";
+ oss << "floating point underflow";
break;
case FPE_FLTRES:
- kwsys_ios::cerr << "floating point inexact result";
+ oss << "floating point inexact result";
break;
case FPE_FLTINV:
- kwsys_ios::cerr << "floating point invalid operation";
+ oss << "floating point invalid operation";
break;
#if defined(FPE_FLTSUB)
case FPE_FLTSUB:
- kwsys_ios::cerr << "floating point subscript out of range";
+ oss << "floating point subscript out of range";
break;
#endif
default:
- kwsys_ios::cerr << "code " << sigInfo->si_code;
+ oss << "code " << sigInfo->si_code;
break;
}
break;
case SIGSEGV:
- kwsys_ios::cerr << "Caught SIGSEGV ";
+ oss << "Caught SIGSEGV ";
switch (sigInfo->si_code)
{
case SEGV_MAPERR:
- kwsys_ios::cerr << "address not mapped to object";
+ oss << "address not mapped to object";
break;
case SEGV_ACCERR:
- kwsys_ios::cerr << "invalid permission for mapped object";
+ oss << "invalid permission for mapped object";
break;
default:
- kwsys_ios::cerr << "code " << sigInfo->si_code;
+ oss << "code " << sigInfo->si_code;
break;
}
break;
case SIGINT:
- kwsys_ios::cerr << "Caught SIGTERM";
+ oss << "Caught SIGTERM";
break;
case SIGTERM:
- kwsys_ios::cerr << "Caught SIGTERM";
+ oss << "Caught SIGTERM";
break;
case SIGBUS:
- kwsys_ios::cerr << "Caught SIGBUS type ";
+ oss << "Caught SIGBUS type ";
switch (sigInfo->si_code)
{
case BUS_ADRALN:
- kwsys_ios::cerr << "invalid address alignment";
+ oss << "invalid address alignment";
break;
# if defined(BUS_ADRERR)
case BUS_ADRERR:
- kwsys_ios::cerr << "non-exestent physical address";
+ oss << "non-exestent physical address";
break;
# endif
# if defined(BUS_OBJERR)
case BUS_OBJERR:
- kwsys_ios::cerr << "object specific hardware error";
+ oss << "object specific hardware error";
break;
# endif
default:
- kwsys_ios::cerr << "code " << sigInfo->si_code;
+ oss << "code " << sigInfo->si_code;
break;
}
break;
case SIGILL:
- kwsys_ios::cerr << "Caught SIGILL ";
+ oss << "Caught SIGILL ";
switch (sigInfo->si_code)
{
case ILL_ILLOPC:
- kwsys_ios::cerr << "illegal opcode";
+ oss << "illegal opcode";
break;
# if defined(ILL_ILLOPN)
case ILL_ILLOPN:
- kwsys_ios::cerr << "illegal operand";
+ oss << "illegal operand";
break;
# endif
# if defined(ILL_ILLADR)
case ILL_ILLADR:
- kwsys_ios::cerr << "illegal addressing mode.";
+ oss << "illegal addressing mode.";
break;
# endif
case ILL_ILLTRP:
- kwsys_ios::cerr << "illegal trap";
+ oss << "illegal trap";
case ILL_PRVOPC:
- kwsys_ios::cerr << "privileged opcode";
+ oss << "privileged opcode";
break;
# if defined(ILL_PRVREG)
case ILL_PRVREG:
- kwsys_ios::cerr << "privileged register";
+ oss << "privileged register";
break;
# endif
# if defined(ILL_COPROC)
case ILL_COPROC:
- kwsys_ios::cerr << "co-processor error";
+ oss << "co-processor error";
break;
# endif
# if defined(ILL_BADSTK)
case ILL_BADSTK:
- kwsys_ios::cerr << "internal stack error";
+ oss << "internal stack error";
break;
# endif
default:
- kwsys_ios::cerr << "code " << sigInfo->si_code;
+ oss << "code " << sigInfo->si_code;
break;
}
break;
default:
- kwsys_ios::cerr << "Caught " << sigNo << " code " << sigInfo->si_code;
+ oss << "Caught " << sigNo << " code " << sigInfo->si_code;
break;
}
- kwsys_ios::cerr << kwsys_ios::endl;
-
+ oss << kwsys_ios::endl;
#if defined(KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE)
- kwsys_ios::cerr << "Stack:" << kwsys_ios::endl;
- void *stack[128];
- int n=backtrace(stack,128);
- backtrace_symbols_fd(stack,n,2);
+ oss << "Program Stack:" << kwsys_ios::endl;
+ void *stackSymbols[128];
+ int n=backtrace(stackSymbols,128);
+ char **stackText=backtrace_symbols(stackSymbols,n);
+ for (int i=0; i<n; ++i)
+ {
+ oss << " " << stackText[i] << kwsys_ios::endl;
+ }
#endif
-
+ oss
+ << "=========================================================" << kwsys_ios::endl;
+ kwsys_ios::cerr << oss.str() << kwsys_ios::endl;
abort();
-
#else
// avoid warning C4100
(void)sigNo;
(void)sigInfo;
#endif
}
+#endif
+} // anonymous namespace
SystemInformationImplementation::SystemInformationImplementation()
{
@@ -1047,6 +1208,29 @@ const char * SystemInformationImplementation::GetOSName()
/** Get the hostname */
const char* SystemInformationImplementation::GetHostname()
{
+ if (this->Hostname.empty())
+ {
+ this->Hostname="localhost";
+#if defined(_WIN32)
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ char name[255];
+ wVersionRequested = MAKEWORD(2,0);
+ if ( WSAStartup( wVersionRequested, &wsaData ) == 0 )
+ {
+ gethostname(name,sizeof(name));
+ WSACleanup( );
+ }
+ this->Hostname = name;
+#else
+ struct utsname unameInfo;
+ int errorFlag = uname(&unameInfo);
+ if(errorFlag == 0)
+ {
+ this->Hostname = unameInfo.nodename;
+ }
+#endif
+ }
return this->Hostname.c_str();
}
@@ -1092,7 +1276,12 @@ int SystemInformationImplementation::GetFullyQualifiedDomainName(
// we want the fully qualified domain name. Because there are
// any number of interfaces on this system we look for the
// first of these that contains the name returned by gethostname
- // and is longer. failing that we return gethostname.
+ // and is longer. failing that we return gethostname and indicate
+ // with a failure code. Return of a failure code is not necessarilly
+ // an indication of an error. for instance gethostname may return
+ // the fully qualified domain name, or there may not be one if the
+ // system lives on a private network such as in the case of a cluster
+ // node.
int ierr=0;
char base[NI_MAXHOST];
@@ -1132,8 +1321,8 @@ int SystemInformationImplementation::GetFullyQualifiedDomainName(
NI_NAMEREQD);
if (ierr)
{
- // don't report the error now since we may succeed on another
- // interface. If all attempts fail then retrun an error code.
+ // don't report the failure now since we may succeed on another
+ // interface. If all attempts fail then return the failure code.
ierr=-3;
continue;
}
@@ -1153,6 +1342,7 @@ int SystemInformationImplementation::GetFullyQualifiedDomainName(
return ierr;
#else
/* TODO: Implement on more platforms. */
+ fqdn=this->GetHostname();
return -1;
#endif
}
@@ -2905,7 +3095,7 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
Get total system RAM in units of KiB.
*/
SystemInformation::LongLong
-SystemInformationImplementation::GetMemoryTotal()
+SystemInformationImplementation::GetHostMemoryTotal()
{
#if defined(_WIN32)
# if defined(_MSC_VER) && _MSC_VER < 1300
@@ -2920,7 +3110,7 @@ SystemInformationImplementation::GetMemoryTotal()
return statex.ullTotalPhys/1024;
# endif
#elif defined(__linux)
- LongLong memTotal=0;
+ SystemInformation::LongLong memTotal=0;
int ierr=GetFieldFromFile("/proc/meminfo","MemTotal:",memTotal);
if (ierr)
{
@@ -2942,15 +3132,156 @@ SystemInformationImplementation::GetMemoryTotal()
}
/**
+Get total system RAM in units of KiB. This may differ from the
+host total if a host-wide resource limit is applied.
+*/
+SystemInformation::LongLong
+SystemInformationImplementation::GetHostMemoryAvailable(const char *hostLimitEnvVarName)
+{
+ SystemInformation::LongLong memTotal=this->GetHostMemoryTotal();
+
+ // the following mechanism is provided for systems that
+ // apply resource limits across groups of processes.
+ // this is of use on certain SMP systems (eg. SGI UV)
+ // where the host has a large amount of ram but a given user's
+ // access to it is severly restricted. The system will
+ // apply a limit across a set of processes. Units are in KiB.
+ if (hostLimitEnvVarName)
+ {
+ const char *hostLimitEnvVarValue=getenv(hostLimitEnvVarName);
+ if (hostLimitEnvVarValue)
+ {
+ SystemInformation::LongLong hostLimit=atoLongLong(hostLimitEnvVarValue);
+ if (hostLimit>0)
+ {
+ memTotal=min(hostLimit,memTotal);
+ }
+ }
+ }
+
+ return memTotal;
+}
+
+/**
+Get total system RAM in units of KiB. This may differ from the
+host total if a per-process resource limit is applied.
+*/
+SystemInformation::LongLong
+SystemInformationImplementation::GetProcMemoryAvailable(
+ const char *hostLimitEnvVarName,
+ const char *procLimitEnvVarName)
+{
+ SystemInformation::LongLong memAvail
+ = this->GetHostMemoryAvailable(hostLimitEnvVarName);
+
+ // the following mechanism is provide for systems where rlimits
+ // are not employed. Units are in KiB.
+ if (procLimitEnvVarName)
+ {
+ const char *procLimitEnvVarValue=getenv(procLimitEnvVarName);
+ if (procLimitEnvVarValue)
+ {
+ SystemInformation::LongLong procLimit=atoLongLong(procLimitEnvVarValue);
+ if (procLimit>0)
+ {
+ memAvail=min(procLimit,memAvail);
+ }
+ }
+ }
+
+#if defined(__linux)
+ int ierr;
+ ResourceLimitType rlim;
+ ierr=GetResourceLimit(RLIMIT_DATA,&rlim);
+ if ((ierr==0) && (rlim.rlim_cur != RLIM_INFINITY))
+ {
+ memAvail=min((SystemInformation::LongLong)rlim.rlim_cur/1024,memAvail);
+ }
+
+ ierr=GetResourceLimit(RLIMIT_AS,&rlim);
+ if ((ierr==0) && (rlim.rlim_cur != RLIM_INFINITY))
+ {
+ memAvail=min((SystemInformation::LongLong)rlim.rlim_cur/1024,memAvail);
+ }
+#elif defined(__APPLE__)
+ struct rlimit rlim;
+ int ierr;
+ ierr=getrlimit(RLIMIT_DATA,&rlim);
+ if ((ierr==0) && (rlim.rlim_cur != RLIM_INFINITY))
+ {
+ memAvail=min((SystemInformation::LongLong)rlim.rlim_cur/1024,memAvail);
+ }
+
+ ierr=getrlimit(RLIMIT_RSS,&rlim);
+ if ((ierr==0) && (rlim.rlim_cur != RLIM_INFINITY))
+ {
+ memAvail=min((SystemInformation::LongLong)rlim.rlim_cur/1024,memAvail);
+ }
+#endif
+
+ return memAvail;
+}
+
+/**
+Get RAM used by all processes in the host, in units of KiB.
+*/
+SystemInformation::LongLong
+SystemInformationImplementation::GetHostMemoryUsed()
+{
+#if defined(_WIN32)
+# if defined(_MSC_VER) && _MSC_VER < 1300
+ MEMORYSTATUS stat;
+ stat.dwLength = sizeof(stat);
+ GlobalMemoryStatus(&stat);
+ return (stat.dwTotalPhys - stat.dwAvailPhys)/1024;
+# else
+ MEMORYSTATUSEX statex;
+ statex.dwLength=sizeof(statex);
+ GlobalMemoryStatusEx(&statex);
+ return (statex.ullTotalPhys - statex.ullAvailPhys)/1024;
+# endif
+#elif defined(__linux)
+ const char *names[3]={"MemTotal:","MemFree:",NULL};
+ SystemInformation::LongLong values[2]={SystemInformation::LongLong(0)};
+ int ierr=GetFieldsFromFile("/proc/meminfo",names,values);
+ if (ierr)
+ {
+ return ierr;
+ }
+ SystemInformation::LongLong &memTotal=values[0];
+ SystemInformation::LongLong &memFree=values[1];
+ return memTotal - memFree;
+#elif defined(__APPLE__)
+ SystemInformation::LongLong psz=getpagesize();
+ if (psz<1)
+ {
+ return -1;
+ }
+ const char *names[4]={"Pages active:","Pages inactive:","Pages wired down:",NULL};
+ SystemInformation::LongLong values[3]={SystemInformation::LongLong(0)};
+ int ierr=GetFieldsFromCommand("vm_stat", names, values);
+ if (ierr)
+ {
+ return -1;
+ }
+ SystemInformation::LongLong &vmActive=values[0];
+ SystemInformation::LongLong &vmInactive=values[1];
+ SystemInformation::LongLong &vmWired=values[2];
+ return ((vmActive+vmInactive+vmWired)*psz)/1024;
+#else
+ return 0;
+#endif
+}
+
+/**
Get system RAM used by the process associated with the given
process id in units of KiB.
*/
SystemInformation::LongLong
-SystemInformationImplementation::GetMemoryUsed()
+SystemInformationImplementation::GetProcMemoryUsed()
{
#if defined(_WIN32) && defined(KWSYS_SYS_HAS_PSAPI)
long pid=GetCurrentProcessId();
-
HANDLE hProc;
hProc=OpenProcess(
PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
@@ -2960,7 +3291,6 @@ SystemInformationImplementation::GetMemoryUsed()
{
return -1;
}
-
PROCESS_MEMORY_COUNTERS pmc;
int ok=GetProcessMemoryInfo(hProc,&pmc,sizeof(pmc));
CloseHandle(hProc);
@@ -2970,7 +3300,7 @@ SystemInformationImplementation::GetMemoryUsed()
}
return pmc.WorkingSetSize/1024;
#elif defined(__linux)
- LongLong memUsed=0;
+ SystemInformation::LongLong memUsed=0;
int ierr=GetFieldFromFile("/proc/self/status","VmRSS:",memUsed);
if (ierr)
{
@@ -2978,23 +3308,34 @@ SystemInformationImplementation::GetMemoryUsed()
}
return memUsed;
#elif defined(__APPLE__)
+ SystemInformation::LongLong memUsed=0;
pid_t pid=getpid();
kwsys_stl::ostringstream oss;
oss << "ps -o rss= -p " << pid;
- FILE *f=popen(oss.str().c_str(),"r");
- if (f==0)
+ FILE *file=popen(oss.str().c_str(),"r");
+ if (file==0)
{
return -1;
}
oss.str("");
- char buf[256]={'\0'};
- while (fgets(buf, 256, f) != 0)
+ while (!feof(file) && !ferror(file))
{
- oss << buf;
+ char buf[256]={'\0'};
+ errno=0;
+ size_t nRead=fread(buf,1,256,file);
+ if (ferror(file) && (errno==EINTR))
+ {
+ clearerr(file);
+ }
+ if (nRead) oss << buf;
+ }
+ int ierr=ferror(file);
+ pclose(file);
+ if (ierr)
+ {
+ return -2;
}
- pclose(f);
kwsys_stl::istringstream iss(oss.str());
- LongLong memUsed=0;
iss >> memUsed;
return memUsed;
#else
@@ -3603,6 +3944,7 @@ bool SystemInformationImplementation::ParseSysCtl()
if ( host_statistics(mach_host_self(), HOST_VM_INFO,
(host_info_t) &vmstat, &count) == KERN_SUCCESS )
{
+ len = sizeof(value);
err = sysctlbyname("hw.pagesize", &value, &len, NULL, 0);
int64_t available_memory = vmstat.free_count * value;
this->AvailablePhysicalMemory = static_cast< size_t >( available_memory / 1048576 );
@@ -3613,7 +3955,7 @@ bool SystemInformationImplementation::ParseSysCtl()
int mib[2] = { CTL_VM, VM_SWAPUSAGE };
size_t miblen = sizeof(mib) / sizeof(mib[0]);
struct xsw_usage swap;
- len = sizeof(struct xsw_usage);
+ len = sizeof(swap);
err = sysctl(mib, miblen, &swap, &len, NULL, 0);
if (err == 0)
{
@@ -3628,6 +3970,7 @@ bool SystemInformationImplementation::ParseSysCtl()
// CPU Info
len = sizeof(this->NumberOfPhysicalCPU);
sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len, NULL, 0);
+ len = sizeof(this->NumberOfLogicalCPU);
sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, NULL, 0);
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
this->LogicalCPUPerPhysicalCPU();
@@ -3653,8 +3996,9 @@ bool SystemInformationImplementation::ParseSysCtl()
if (machineBuf.find_first_of("Power") != kwsys_stl::string::npos)
{
this->ChipID.Vendor = "IBM";
- len = 4;
+ len = sizeof(this->ChipID.Family);
err = sysctlbyname("hw.cputype", &this->ChipID.Family, &len, NULL, 0);
+ len = sizeof(this->ChipID.Model);
err = sysctlbyname("hw.cpusubtype", &this->ChipID.Model, &len, NULL, 0);
this->FindManufacturer();
}
@@ -3679,8 +4023,8 @@ bool SystemInformationImplementation::ParseSysCtl()
}
// brand string
- ::memset(retBuf, 0, 128);
- len = 128;
+ ::memset(retBuf, 0, sizeof(retBuf));
+ len = sizeof(retBuf);
err = sysctlbyname("machdep.cpu.brand_string", retBuf, &len, NULL, 0);
if (!err)
{
@@ -3692,6 +4036,7 @@ bool SystemInformationImplementation::ParseSysCtl()
len = sizeof(value);
err = sysctlbyname("hw.l1icachesize", &value, &len, NULL, 0);
this->Features.L1CacheSize = static_cast< int >( value );
+ len = sizeof(value);
err = sysctlbyname("hw.l2cachesize", &value, &len, NULL, 0);
this->Features.L2CacheSize = static_cast< int >( value );