Просмотр исходного кода

KWSys 2012-10-16 (b7a97ac3)

Extract upstream KWSys using the following shell commands.

$ git archive --prefix=upstream-kwsys/ b7a97ac3 | tar x
$ git shortlog --no-merges --abbrev=8 --format='%h %s' bab53989..b7a97ac3
Brad King (3):
      f9db7eab SystemInformation: Fix helper definition order
      a1e83e42 SystemInformation: Expose helper functions only where needed
      b7a97ac3 SystemInformation: Drop unused LoadLines on OS X

Burlen Loring (1):
      6072e63b SystemInformation: support for resource limits

Sean McBride (2):
      a536d833 ProcessUNIX: Suppress warning about uninteresting return code
      00852081 SystemInformation: Fix sloppy use of sysctlbyname() API

Change-Id: Iae8af129a021435ef4e6daef255e312c99d7b773
KWSys Robot 13 лет назад
Родитель
Сommit
7ae44db4b9
6 измененных файлов с 657 добавлено и 133 удалено
  1. 61 4
      CMakeLists.txt
  2. 1 0
      ProcessUNIX.c
  3. 460 115
      SystemInformation.cxx
  4. 39 10
      SystemInformation.hxx.in
  5. 66 0
      kwsysPlatformTestsCXX.cxx
  6. 30 4
      testSystemInformation.cxx

+ 61 - 4
CMakeLists.txt

@@ -509,19 +509,28 @@ ENDIF(KWSYS_USE_FundamentalType)
 
 IF(KWSYS_USE_IOStream)
   # Determine whether iostreams support long long.
+  SET(KWSYS_PLATFORM_CXX_TEST_DEFINES
+    -DKWSYS_IOS_USE_ANSI=${KWSYS_IOS_USE_ANSI}
+    -DKWSYS_IOS_HAVE_STD=${KWSYS_IOS_HAVE_STD})
   IF(KWSYS_CXX_HAS_LONG_LONG)
-    SET(KWSYS_PLATFORM_CXX_TEST_DEFINES
-      -DKWSYS_IOS_USE_ANSI=${KWSYS_IOS_USE_ANSI}
-      -DKWSYS_IOS_HAVE_STD=${KWSYS_IOS_HAVE_STD})
     KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_ISTREAM_LONG_LONG
       "Checking if istream supports long long" DIRECT)
     KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_OSTREAM_LONG_LONG
       "Checking if ostream supports long long" DIRECT)
-    SET(KWSYS_PLATFORM_CXX_TEST_DEFINES)
   ELSE()
     SET(KWSYS_IOS_HAS_ISTREAM_LONG_LONG 0)
     SET(KWSYS_IOS_HAS_OSTREAM_LONG_LONG 0)
   ENDIF()
+  IF(KWSYS_CXX_HAS___INT64)
+    KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_ISTREAM___INT64
+      "Checking if istream supports __int64" DIRECT)
+    KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_OSTREAM___INT64
+      "Checking if ostream supports __int64" DIRECT)
+  ELSE()
+    SET(KWSYS_IOS_HAS_ISTREAM___INT64 0)
+    SET(KWSYS_IOS_HAS_OSTREAM___INT64 0)
+  ENDIF()
+  SET(KWSYS_PLATFORM_CXX_TEST_DEFINES)
 ENDIF(KWSYS_USE_IOStream)
 
 IF(KWSYS_NAMESPACE MATCHES "^kwsys$")
@@ -588,6 +597,54 @@ IF(KWSYS_USE_SystemInformation)
       ENDIF()
     ENDIF()
   ENDIF()
+  IF(KWSYS_LFS_AVAILABLE AND NOT KWSYS_LFS_DISABLE)
+    SET(KWSYS_PLATFORM_CXX_TEST_DEFINES -DKWSYS_HAS_LFS=1)
+  ENDIF()
+  KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_RLIMIT64
+    "Checking whether CXX compiler has rlimit64" DIRECT)
+  SET(KWSYS_PLATFORM_CXX_TEST_DEFINES)
+  IF(KWSYS_CXX_HAS_RLIMIT64)
+    SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+      COMPILE_DEFINITIONS KWSYS_CXX_HAS_RLIMIT64=1)
+  ENDIF()
+  KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ATOL
+    "Checking whether CXX compiler has atol" DIRECT)
+  IF(KWSYS_CXX_HAS_ATOL)
+    SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+      COMPILE_DEFINITIONS KWSYS_CXX_HAS_ATOL=1)
+  ENDIF()
+  KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ATOLL
+    "Checking whether CXX compiler has atoll" DIRECT)
+  IF(KWSYS_CXX_HAS_ATOLL)
+    SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+      COMPILE_DEFINITIONS KWSYS_CXX_HAS_ATOLL=1)
+  ENDIF()
+  KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS__ATOI64
+    "Checking whether CXX compiler has _atoi64" DIRECT)
+  IF(KWSYS_CXX_HAS__ATOI64)
+    SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+      COMPILE_DEFINITIONS KWSYS_CXX_HAS__ATOI64=1)
+  ENDIF()
+  IF(KWSYS_USE___INT64)
+    SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY
+      COMPILE_DEFINITIONS KWSYS_USE___INT64=1)
+  ENDIF()
+  IF(KWSYS_USE_LONG_LONG)
+    SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY
+      COMPILE_DEFINITIONS KWSYS_USE_LONG_LONG=1)
+  ENDIF()
+  IF(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
+    SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY
+      COMPILE_DEFINITIONS KWSYS_IOS_HAS_OSTREAM_LONG_LONG=1)
+  ENDIF()
+  IF(KWSYS_IOS_HAS_OSTREAM___INT64)
+    SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY
+      COMPILE_DEFINITIONS KWSYS_IOS_HAS_OSTREAM___INT64=1)
+  ENDIF()
+  IF(KWSYS_BUILD_SHARED)
+    SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+      COMPILE_DEFINITIONS KWSYS_BUILD_SHARED=1)
+  ENDIF()
 ENDIF()
 
 #-----------------------------------------------------------------------------

+ 1 - 0
ProcessUNIX.c

@@ -2732,6 +2732,7 @@ static void kwsysProcessesSignalHandler(int signum
     kwsysProcess* cp = kwsysProcesses.Processes[i];
     kwsysProcess_ssize_t status=
       read(cp->PipeReadEnds[KWSYSPE_PIPE_SIGNAL], &buf, 1);
+    (void)status;
     status=write(cp->SignalPipe, &buf, 1);
     (void)status;
     }

+ 460 - 115
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)
     {
@@ -2941,16 +3131,157 @@ SystemInformationImplementation::GetMemoryTotal()
 #endif
 }
 
+/**
+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 );
 

+ 39 - 10
SystemInformation.hxx.in

@@ -24,7 +24,6 @@
 namespace @KWSYS_NAMESPACE@
 {
 
-
 // forward declare the implementation class
 class SystemInformationImplementation;
 
@@ -96,15 +95,44 @@ public:
   size_t GetTotalPhysicalMemory();
   size_t GetAvailablePhysicalMemory();
 
-  // returns an informative general description if the ram
-  // on this system
-  kwsys_stl::string GetMemoryDescription();
-
-  // Retrieve physical memory information in kib
-  LongLong GetMemoryTotal();
-  LongLong GetMemoryUsed();
-
-  // enable/disable stack trace signal handler.
+  // returns an informative general description if the installed and
+  // available ram on this system. See the  GetHostMmeoryTotal, and
+  // Get{Host,Proc}MemoryAvailable methods for more information.
+  kwsys_stl::string GetMemoryDescription(
+        const char *hostLimitEnvVarName=NULL,
+        const char *procLimitEnvVarName=NULL);
+
+  // Retrieve amount of physical memory installed on the system in KiB
+  // units.
+  LongLong GetHostMemoryTotal();
+
+  // Get total system RAM in units of KiB available colectivley to all
+  // processes in a process group. An example of a process group
+  // are the processes comprising an mpi program which is running in
+  // parallel. The amount of memory reported may differ from the host
+  // total if a host wide resource limit is applied. Such reource limits
+  // are reported to us via an applicaiton specified environment variable.
+  LongLong GetHostMemoryAvailable(const char *hostLimitEnvVarName=NULL);
+
+  // Get total system RAM in units of KiB available to this process.
+  // This may differ from the host available if a per-process resource
+  // limit is applied. per-process memory limits are applied on unix
+  // system via rlimit api. Resource limits that are not imposed via
+  // rlimit api may be reported to us via an application specified
+  // environment variable.
+  LongLong GetProcMemoryAvailable(
+        const char *hostLimitEnvVarName=NULL,
+        const char *procLimitEnvVarName=NULL);
+
+  // Get the system RAM used by all processes on the host, in units of KiB.
+  LongLong GetHostMemoryUsed();
+
+  // Get system RAM used by this process id in units of KiB.
+  LongLong GetProcMemoryUsed();
+
+  // enable/disable stack trace signal handler. In order to
+  // produce an informative stack trace the application should
+  // be dynamically linked and compiled with debug symbols.
   static
   void SetStackTraceOnError(int enable);
 
@@ -113,6 +141,7 @@ public:
   void RunOSCheck();
   void RunMemoryCheck();
 };
+
 } // namespace @KWSYS_NAMESPACE@
 
 /* Undefine temporary macros.  */

+ 66 - 0
kwsysPlatformTestsCXX.cxx

@@ -358,6 +358,30 @@ int main()
 }
 #endif
 
+#ifdef TEST_KWSYS_IOS_HAS_ISTREAM___INT64
+int test_istream(kwsys_ios::istream& is, __int64& x)
+{
+  return (is >> x)? 1:0;
+}
+int main()
+{
+  __int64 x = 0;
+  return test_istream(kwsys_ios::cin, x);
+}
+#endif
+
+#ifdef TEST_KWSYS_IOS_HAS_OSTREAM___INT64
+int test_ostream(kwsys_ios::ostream& os, __int64 x)
+{
+  return (os << x)? 1:0;
+}
+int main()
+{
+  __int64 x = 0;
+  return test_ostream(kwsys_ios::cout, x);
+}
+#endif
+
 #ifdef TEST_KWSYS_CHAR_IS_SIGNED
 /* Return 0 for char signed and 1 for char unsigned.  */
 int main()
@@ -428,6 +452,48 @@ int main()
 }
 #endif
 
+#ifdef TEST_KWSYS_CXX_HAS_RLIMIT64
+# if defined(KWSYS_HAS_LFS)
+#  define _LARGEFILE_SOURCE
+#  define _LARGEFILE64_SOURCE
+#  define _LARGE_FILES
+#  define _FILE_OFFSET_BITS 64
+# endif
+# include <sys/resource.h>
+int main()
+{
+  struct rlimit64 rlim;
+  return getrlimit64(0,&rlim);
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_ATOLL
+#include <stdlib.h>
+int main()
+{
+  const char *str="1024";
+  return static_cast<int>(atoll(str));
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_ATOL
+#include <stdlib.h>
+int main()
+{
+  const char *str="1024";
+  return static_cast<int>(atol(str));
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS__ATOI64
+#include <stdlib.h>
+int main()
+{
+  const char *str="1024";
+  return static_cast<int>(_atoi64(str));
+}
+#endif
+
 #ifdef TEST_KWSYS_CXX_TYPE_INFO
 /* Collect fundamental type information and save it to a CMake script.  */
 

+ 30 - 4
testSystemInformation.cxx

@@ -13,8 +13,6 @@
 #include KWSYS_HEADER(SystemInformation.hxx)
 #include KWSYS_HEADER(ios/iostream)
 
-
-
 // Work-around CMake dependency scanning limitation.  This must
 // duplicate the above list of headers.
 #if 0
@@ -22,12 +20,31 @@
 # include "kwsys_ios_iostream.h.in"
 #endif
 
-#define printMethod(inof, m) kwsys_ios::cout << #m << ": " \
+#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
+
+#define printMethod(info, m) kwsys_ios::cout << #m << ": " \
 << info.m() << "\n"
 
-#define printMethod2(inof, m, unit) kwsys_ios::cout << #m << ": " \
+#define printMethod2(info, m, unit) kwsys_ios::cout << #m << ": " \
 << info.m() << " " << unit << "\n"
 
+#define printMethod3(info, m, unit) kwsys_ios::cout << #m << ": " \
+<< iostreamLongLong(info.m) << " " << unit << "\n"
+
 int testSystemInformation(int, char*[])
 {
   kwsys::SystemInformation info;
@@ -35,7 +52,11 @@ int testSystemInformation(int, char*[])
   info.RunOSCheck();
   info.RunMemoryCheck();
   printMethod(info, GetOSName);
+  printMethod(info, GetOSIsLinux);
+  printMethod(info, GetOSIsApple);
+  printMethod(info, GetOSIsWindows);
   printMethod(info, GetHostname);
+  printMethod(info, GetFullyQualifiedDomainName);
   printMethod(info, GetOSRelease);
   printMethod(info, GetOSVersion);
   printMethod(info, GetOSPlatform);
@@ -58,6 +79,11 @@ int testSystemInformation(int, char*[])
   printMethod2(info, GetAvailableVirtualMemory, "MB");
   printMethod2(info, GetTotalPhysicalMemory, "MB");
   printMethod2(info, GetAvailablePhysicalMemory, "MB");
+  printMethod3(info, GetHostMemoryTotal(), "KiB");
+  printMethod3(info, GetHostMemoryAvailable("KWSHL"), "KiB");
+  printMethod3(info, GetProcMemoryAvailable("KWSHL","KWSPL"), "KiB");
+  printMethod3(info, GetHostMemoryUsed(), "KiB");
+  printMethod3(info, GetProcMemoryUsed(), "KiB");
 
   //int GetProcessorCacheXSize(long int);
 //  bool DoesCPUSupportFeature(long int);